一些关于调度的疑问

来源:1-4 Go 程序是怎么跑起来的

tan_beta

2021-06-22 22:24:52

  1. 在程序启动mstart函数中,runtime.main执行main.main,如果main.main直接返回了,那么是不是不会进入到调度循环了?在runtime.mstart1中,main.main执行完了之后才会进入到schedule循环中。
  2. ppt中说的main.main中有调度循环,是因为上面多了一个defer么?所以他根本走不到main结束,直接就去schedule了?
  3. 如果main.main中有协程产生并且阻塞,我们会开一个新的m去运行产生的协程,那么这个新的m的调度就跟m0的调度不是一样的了吧?
  4. 在mstart1中,如果_g_.m != &m , 会将_g_.m.nextp和 m关联起来,为什么?
  5. 为什么mstart中不是用g0和m0去执行main.main,而是新建的一个g呢?
写回答

4回答

Xargin

2021-06-23

  1. 在程序启动mstart函数中,runtime.main执行main.main,如果main.main直接返回了,那么是不是不会进入到调度循环了?在runtime.mstart1中,main.main执行完了之后才会进入到schedule循环中。


    1. 你的意思是 main.main 执行很短一段时间就退出了吧,这种情况下,runtime.main 里的 f() 会返回,然后一路走到最后,整个进程就退出了

    2. main.main 得碰到能接管的阻塞的时候,就是第一课 ppt 里那几种情况,m0 就会把这个 main goroutine 给 park 起来,然后重新进入调度循环。

    3. main.main 如果执行完了,那后面直接调用 exit,整个进程就退出了,和调度循环啥的也没啥关系了

  2. ppt中说的main.main中有调度循环,是因为上面多了一个defer么?所以他根本走不到main结束,直接就去schedule了?


    1. ppt 那里的意思是 m0 会负责执行 main.main,然后如果 main.main 有可接管的阻塞,后面 m0 是可以进调度循环的,进了 schedule 以后其实就和普通的线程没啥区别了~

    2. 第一课直播讲的时候的图稍微有点问题~

  3. 如果main.main中有协程产生并且阻塞,我们会开一个新的m去运行产生的协程,那么这个新的m的调度就跟m0的调度不是一样的了吧?


    1. main.main 本身就是在 main goroutine 里执行的,他阻塞的话,和其它 goroutine 阻塞没啥区别~

    2. 如果是我们之前说的可接管的阻塞,那 m0 可以直接进调度循环去执行在 main 函数里创建的 goroutine~

    3. 如果 main.main 的阻塞是 syscall 那种不可接管的,那 m0 就暂时被占用了,确实需要启动其它的 m 去执行调度

    4. 进调度循环的线程都是一视同仁的,只不过 m0 只是初始线程,这个我印象中是操作系统帮我们创建的(就是其它语言里的主线程),除 m0 以外的其它的线程都是在 Go 里面主动调用 syscall.Clone 创建的

  4. 在mstart1中,如果_g_.m != &m , 会将_g_.m.nextp和 m关联起来,为什么?

    1. 这里我看了看代码,就是启动新线程的时候,newm -> startm 是已经把这个 m 应该绑的 p 设置在 m.nextp 里了。。。到了 mstart 过程只是绑定一下,好像也没看出什么特殊的


  5. 为什么mstart中不是用g0和m0去执行main.main,而是新建的一个g呢?

    1. g0 在所有 m 里都是一个特殊的 g,只能用来执行 runtime 里的调度函数,在执行过程中不能影响到用户的运行栈,一般是 system_stack 或者 mcall 的时候会进去

    2. 对于 runtime 来说,main.main 也是用户代码(runtime.main 也是),所有用户代码都应该在专门的 user g 里执行

0
hargin
hp style="padding:0px;color:rgb(7,17,27);font-family:'PingFang SC', '微软雅黑', 'Microsoft YaHei', Helvetica, 'Helvetica Neue', Tahoma, Arial, sans-serif;white-space:normal;background-color:rgb(248,250,252);">fix : 这种好像是老 unix 的传统,相当于 unreachble 的代码 panic 能快速发现 bug

h021-06-23
共3条回复

tan_beta

提问者

2021-06-22

第五个问题是因为调度需要切换g0去进行调度循环么?

1
hargin
hp>对的,g0 主要就是用来执行调度循环的~

h021-06-23
共1条回复

Xargin

2021-06-23

看代码的时候需要知道啥时候会切栈,

要看 system_stack 和 mcall,以及 gogo 之类的代码


这几个好像都是汇编实现的,不过注释写清楚了

0

tan_beta

提问者

2021-06-22

main中不是只有

runningPanicDefers != 0

时,才能进入到调度循环么?我看这个

runningPanicDefers

的注释是说 当要退出时,另外一个协程发生了panic,才会不为0。那么这里main里面还有其他地方进去到调度循环么?

0
hargin
hp>执行调度循环的是线程,不是 goroutine..

h021-06-23
共1条回复

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程