一些关于调度的疑问
来源:1-4 Go 程序是怎么跑起来的
tan_beta
2021-06-22 22:24:52
4回答
在程序启动mstart函数中,runtime.main执行main.main,如果main.main直接返回了,那么是不是不会进入到调度循环了?在runtime.mstart1中,main.main执行完了之后才会进入到schedule循环中。
你的意思是 main.main 执行很短一段时间就退出了吧,这种情况下,runtime.main 里的 f() 会返回,然后一路走到最后,整个进程就退出了
main.main 得碰到能接管的阻塞的时候,就是第一课 ppt 里那几种情况,m0 就会把这个 main goroutine 给 park 起来,然后重新进入调度循环。
main.main 如果执行完了,那后面直接调用 exit,整个进程就退出了,和调度循环啥的也没啥关系了
ppt中说的main.main中有调度循环,是因为上面多了一个defer么?所以他根本走不到main结束,直接就去schedule了?
ppt 那里的意思是 m0 会负责执行 main.main,然后如果 main.main 有可接管的阻塞,后面 m0 是可以进调度循环的,进了 schedule 以后其实就和普通的线程没啥区别了~
第一课直播讲的时候的图稍微有点问题~
如果main.main中有协程产生并且阻塞,我们会开一个新的m去运行产生的协程,那么这个新的m的调度就跟m0的调度不是一样的了吧?
main.main 本身就是在 main goroutine 里执行的,他阻塞的话,和其它 goroutine 阻塞没啥区别~
如果是我们之前说的可接管的阻塞,那 m0 可以直接进调度循环去执行在 main 函数里创建的 goroutine~
如果 main.main 的阻塞是 syscall 那种不可接管的,那 m0 就暂时被占用了,确实需要启动其它的 m 去执行调度
进调度循环的线程都是一视同仁的,只不过 m0 只是初始线程,这个我印象中是操作系统帮我们创建的(就是其它语言里的主线程),除 m0 以外的其它的线程都是在 Go 里面主动调用 syscall.Clone 创建的
在mstart1中,如果_g_.m != &m , 会将_g_.m.nextp和 m关联起来,为什么?
这里我看了看代码,就是启动新线程的时候,newm -> startm 是已经把这个 m 应该绑的 p 设置在 m.nextp 里了。。。到了 mstart 过程只是绑定一下,好像也没看出什么特殊的
为什么mstart中不是用g0和m0去执行main.main,而是新建的一个g呢?
g0 在所有 m 里都是一个特殊的 g,只能用来执行 runtime 里的调度函数,在执行过程中不能影响到用户的运行栈,一般是 system_stack 或者 mcall 的时候会进去
对于 runtime 来说,main.main 也是用户代码(runtime.main 也是),所有用户代码都应该在专门的 user g 里执行
tan_beta
提问者
2021-06-22
第五个问题是因为调度需要切换g0去进行调度循环么?
Xargin
2021-06-23
看代码的时候需要知道啥时候会切栈,
要看 system_stack 和 mcall,以及 gogo 之类的代码
这几个好像都是汇编实现的,不过注释写清楚了
tan_beta
提问者
2021-06-22
main中不是只有
runningPanicDefers != 0
时,才能进入到调度循环么?我看这个
runningPanicDefers
的注释是说 当要退出时,另外一个协程发生了panic,才会不为0。那么这里main里面还有其他地方进去到调度循环么?
相似问题