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 關注
- 250 瀏覽
添加回答
舉報