2 回答
TA贡献1798条经验 获得超3个赞
从 Go 代码调用 C 函数不会阻止其他 goroutine 运行。
它确实对调度程序有影响。运行 C 函数的 goroutine 不一定要计入GOMAXPROCS限制。它将开始计算 GOMAXPROCS,但是如果 C 函数在 sysmon 后台 goroutine 运行时阻塞了超过 20us,那么如果有一个准备运行的 goroutine,调度程序将被允许启动另一个 goroutine。这些细节取决于特定的 Go 版本,可能会发生变化。
TA贡献1982条经验 获得超2个赞
这是一个非常好的问题,除了代码之外,我没有立即找到任何官方声明。我很高兴对官方文档有任何提示。
答案是否定的, cgo 调用不会阻塞调度程序。
对于以下内容,很高兴知道 Go 在内部使用G表示 goroutine,M表示机器(线程),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调用够程到操作系统的线程),运行时分配一个新的OS线程(理论上超过GOMAXPROCS)。
- 2 回答
- 0 关注
- 225 浏览
添加回答
举报