2016-12-25 7 views
0

오늘 내 친구가 Go 프로그램을 여러 CPU 코어에서 확장 할 수 있다고 말했습니다. 나는 시스템 작업 스케줄러가 goroutines에 대해 아무 것도 모르기 때문에 여러 코어에서 실행할 수 없다는 사실을 알고 놀랐다.골란, 프로세스 및 공유 메모리

몇 가지 검색을 수행했는데 Go 프로그램이 여러 코어에서 실행되도록 여러 OS 작업을 생성 할 수 있음을 알았습니다 (번호는 GOMAXPROCS 환경 변수로 제어됩니다). 그러나 내가 알고있는 한 프로세스를 완료하면 프로세스 데이터가 완전하게 복사되고 다른 프로세스가 다른 주소 공간에서 실행됩니다.

그래서 Go 프로그램의 전역 변수는 어떻습니까? 여러 goroutine과 함께 사용하는 것이 안전합니까? 시스템 프로세스간에 어떻게 든 동기화됩니까? 그리고 그들이 어떻게한다면? 나는 주로 리눅스와 프리 BSD 구현에 대해 우려하고있다.

+2

[goroutines의 공식 문서] (https://golang.org/doc/effective_go.html#goroutines)가 도움이됩니다. – chrk

+0

[이 기사] (https://www.goinggo.net/2014/01/concurrency-goroutines-and-gomaxprocs.html). – chrk

+0

@chrk 문제는 다음과 같습니다. 공식 문서 또는 두 번째 기사가 런타임에 공유 변수의 동기화를 제공하는 방법에 대해 설명하지 않았습니다. 공식 문서에는 "goroutine은 간단한 모델을 가지고 있습니다 : 이것은 동일한 주소 공간에서 다른 goroutine과 동시에 실행되는 함수입니다". 그러나 그들은 서로 다른 프로세스에 있다면 같은 주소 공간에있을 수 없습니다. ... – ea7ababe

답변

4

나는 그것을 알아 냈다! 그것은 모두 출처입니다.

내가 알지 못하는 Linux 시스템 호출이 있습니다. "복제본"이라고합니다. 그것은 포크보다 융통성이 있으며, 자식 프로세스가 부모의 주소 공간에 살도록 허용합니다.

다음은 스레드 생성 프로세스에 대한 간략한 개요입니다.

먼저 src/runtime/proc.gonewm 기능이 있습니다. 이 함수는 새로운 작업 스레드 (또는 주석으로 호출 된 기계)을 생성합니다.

// 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)) 
} 

이 기능은 OS에 고유 newosproc 통화. 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 프로그램은 을 CPU에 걸쳐 사용할 수 있도록하는 여러 OS 스레드에서 실행되지만 하나의 공유 주소 공간을 사용합니다.

피 ... 나는 사랑합니다.