当我从goroutine调用C代码时,它是否会以任何方式影响其他goroutine的调度?我知道如果我在Erlang中调用NIF,它会阻止其他(Erlang)进程,直到函数返回。这是Golang的情况吗? C代码是否会阻止goroutines调度程序?
答案 0 :(得分:11)
从Go代码调用C函数不会阻止其他goroutine运行。
它确实对调度程序有影响。运行C函数的goroutine不一定会计入GOMAXPROCS限制。它将从GOMAXPROCS开始计数,但如果在sysmon后台goroutine运行时C函数已被阻塞超过20us,那么如果有一个准备好运行,则允许调度程序启动另一个goroutine。这些细节取决于具体的Go版本,可能会有所变化。
答案 1 :(得分:8)
这是一个非常好的问题,除了代码之外,我没有找到任何正式的声明。我会很高兴任何官方文件的提示。
答案是不,cgo调用不会阻止调度程序。
对于以下内容,我们很高兴知道内部Go对于goroutines使用 G ,对于机器(线程)使用 M 而对于proccessor使用 P 。 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调用goroutine锁定到OS线程)使运行时能够分配新的OS线程(理论上超过GOMAXPROCS
)。