一些关于调度的疑问
- 在程序启动mstart函数中,runtime.main执行main.main,如果main.main直接返回了,那么是不是不会进入到调度循环了?在runtime.mstart1中,main.main执行完了之后才会进入到schedule循环中。
- ppt中说的main.main中有调度循环,是因为上面多了一个defer么?所以他根本走不到main结束,直接就去schedule了?
- 如果main.main中有协程产生并且阻塞,我们会开一个新的m去运行产生的协程,那么这个新的m的调度就跟m0的调度不是一样的了吧?
- 在mstart1中,如果_g_.m != &m , 会将_g_.m.nextp和 m关联起来,为什么?
- 为什么mstart中不是用g0和m0去执行main.main,而是新建的一个g呢?
正在回答
在程序启动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 里执行
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星