Golang,进程和共享内存

邪恶的

今天,我的一个朋友告诉我,Go程序可以在多个CPU内核上进行扩展。听到系统任务调度程序对goroutine一无所知,因此无法在多个内核上运行它们,我感到非常惊讶。

我进行了一些搜索,发现Go程序可以产生多个OS任务以在不同的内核上运行它们(该数目由GOMAXPROCS环境变量控制)。但是据我所知,对流程进行分叉可导致流程数据的完整复制,并且不同的流程在不同的地址空间中运行。

那么Go程序中的全局变量呢?它们可以安全地与多个goroutine一起使用吗?它们是否以某种方式在系统进程之间同步?如果他们这样做,那又如何?我主要关注linux和freebsd的实现。

邪恶的

我想到了!全部使用源代码。

我没有意识到有一个Linux系统调用。它称为“克隆”。它比fork更灵活,它允许子进程驻留在其父进程的地址空间中。

这是线程创建过程的简短概述。

首先,中有一个newm功能src/runtime/proc.go此函数负责创建新的工作线程(或在注释中称为机器的工作线程)。

// Create a new m. It will start off with a call to fn, or else the scheduler.
// fn needs to be static and not a heap allocated closure.
// May run with m.p==nil, so write barriers are not allowed.
//go:nowritebarrier
func newm(fn func(), _p_ *p) {

    // ... some code skipped ...

    newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
}

此函数调用newosproc特定于OS的函数对于Linux,可以在中找到src/runtime/os_linux.go这是该文件的相关部分:

var (
    // ...

    cloneFlags = _CLONE_VM | /* share memory */
        _CLONE_FS | /* share cwd, etc */
        _CLONE_FILES | /* share fd table */
        _CLONE_SIGHAND | /* share sig handler table */
        _CLONE_THREAD /* revisit - okay for now */
)

// May run with m.p==nil, so write barriers are not allowed.
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {

    // ... some code skipped ...

    ret := clone(cloneFlags, /* ... other flags ... */)

    // ... code skipped
}

clone功能在特定于体系结构的文件中定义。对于amd64,它位于中src/runtime/sys_linux_amd64.s这是实际的系统调用。

因此,Go程序确实可以在多个OS线程中运行,从而可以跨越多个CPU,但是它们使用一个共享的地址空间。

ew ...我爱围棋。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章