作者:佳人蔚虹的小资心情_396 | 来源:互联网 | 2023-05-23 11:53
当我从goroutine调用C代码时,它是否会以任何方式影响其他goroutine的调度?我知道如果我在Erlang中调用NIF,它会阻止其他(Erlang)进程,直到函数返回.这是Golang的情况吗?C代码是否会阻止goroutines调度程序?
1> iant..:
从Go代码调用C函数不会阻止其他goroutine运行.
它确实对调度程序有影响.运行C函数的goroutine不一定会计入GOMAXPROCS限制.它将从GOMAXPROCS开始计数,但如果在sysmon后台goroutine运行时C函数已被阻塞超过20us,那么如果有一个准备好运行,则允许调度程序启动另一个goroutine.这些细节取决于具体的Go版本,可能会有所变化.
2> nemo..:
这是一个非常好的问题,除了代码之外,我没有找到任何正式的声明.我会很高兴任何官方文件的提示.
答案是否定的,cgo调用不会阻止调度程序.
对于以下内容,我们很高兴知道内部Go使用G代表goroutines,M代表机器(线程)而P代表proccessor.Goroutines运行在机器上运行的处理器上.
根据代码文档,从G调用C函数的工作原理如下:
// To call into the C function f from Go, the cgo-generated code calls
// runtime.cgocall(_cgo_Cfunc_f, frame), where _cgo_Cfunc_f is a
// gcc-compiled function written by cgo.
//
// runtime.cgocall (below) locks g to m, calls entersyscall
// so as not to block other goroutines or the garbage collector,
// and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame).
//
// runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack
// (assumed to be an operating system-allocated stack, so safe to run
// gcc-compiled code on) and calls _cgo_Cfunc_f(frame).
//
// _cgo_Cfunc_f invokes the actual C function f with arguments
// taken from the frame structure, records the results in the frame,
// and returns to runtime.asmcgocall.
//
// After it regains control, runtime.asmcgocall switches back to the
// original g (m->curg)'s stack and returns to runtime.cgocall.
//
// After it regains control, runtime.cgocall calls exitsyscall, which blocks
// until this m can run Go code without violating the $GOMAXPROCS limit,
// and then unlocks g from m.
entersyscall
本质上告诉运行时这个goroutine现在处于"外部"控制之下,就像我们对内核进行系统调用的情况一样.另一种可能是有用的一点是,锁定g
到m
(锁定CGO调用够程到操作系统的线程),运行时分配一个新的OS线程(理论上超过GOMAXPROCS
).