2015-02-06 1 views

답변

19

당신은 아마 syscall 패키지 syscall.ForkExec()합니다.

fork()은 스레드가 전혀 사용되지 않았을 때 만들어졌으며 프로세스는 항상 하나의 스레드 만 실행 했으므로 forking이 안전하다는 점에 유의하십시오. Go를 사용하면 상황에 따라 OS 레벨 스레드를 많이 사용하여 goroutine 일정을 강화할 수 있습니다.

이제 자식 프로세스를 만들 것입니다 리눅스에 꾸밈이 fork(2) 그냥 단일 스레드 — 이동 런타임에서 사용되는 몇 가지 중요한 스레드를 포함하여, 활성화 된 모든 중 부모 프로세스 —에 fork(2)라는 사람이있다. 기본적으로이 말은 단순히 이 자식 코드 procss가 GO 코드 인을 계속 실행할 수 있다는 것을 기대할 수 없다는 것을 의미하며 사용자가 현명하게 수행 할 수있는 유일한 방법은 바로 exec(2)을 수행하는 것입니다. 이것이 syscall.ForkExec()에 사용되는 것으로 가정됩니다.

이제 문제에 대해 더 생각해보십시오. 지금은 fork(2)에 대한 직접 호출이 "최선형 비동기 프로세스 상태 스냅 샷"인 경우 과 같은 종류의 —을 사용하는 것이 유일한 요즘이라고 말하고 싶습니다. 이 기법은 자식 프로세스가 부모로부터 모든 메모리 데이터 페이지를 상속 받지만 운영 체제는 모든 데이터를 실제로 복사하지 않기 위해 복사시 복사 기법을 사용하므로 자식이 거기 앉아서 모든 데이터 구조를 저장할 수 있습니다 부모가 자신의 주소 공간에서 수정하는 동안 디스크에 저장됩니다. fork()에 대한 다른 모든 사용은 즉시 exec()을 의미하며 그게 exec.Command() 외의 것이므로 사용하지 않는 이유는 무엇입니까?

+4

"fork()에 대한 다른 모든 사용은 즉각적인 exec()를 의미하며 exec.Command() 외의 것이므로 사용하지 않는 이유는 무엇입니까? setrlimit(), SELinux 설정, chroot() ing, 제어권을 양도하기 전에 FD를 닫거나 설정하는 것, 그리고 fork()와 exec() 사이에서 일어날 필요가있는 것입니까? –

+0

"최선형 비동기 프로세스 상태 스냅 샷"이 * 정확하게 * 무엇을하려하는지? – cpcallen

+1

@cpcallen, 나는 두렵다. "이런 식으로 진행하지 않을 것이다"* 이런 식으로. * 문제의 핵심은 Go 런타임이 OS 레벨 스레드에 대해 두 가지 일을한다는 것이다. a) goroutine ; b) 자신의 필요에 따라 사용합니다.단 하나의 쓰레드 만이 새로운 프로세스에서 다시 시작 되 자마자'fork()'에서 살아남 았기 때문에, 제대로 작동하는 것이 불가능한 절반의 상태가 될 것입니다. – kostix

0

하나의 해결 방법은 해당 goroutine에서 실행되는 exec.Command을 사용하는 것입니다.

작은 프로젝트가 수행 akshaydeo/go_process 것입니다 그 :

// Method to fork a process for given command 
// and return ProcessMonitor 
func Fork(processStateListener ProcessStateListener, cmdName string, cmdArgs ...string) { 
    go func() { 
     processMonitor := &ProcessMonitor{} 
     args := strings.Join(cmdArgs, ",") 
     command := exec.Command(cmdName, args) 
     output, err := command.Output() 
     if err != nil { 
      processMonitor.Err = err 
      processStateListener.OnError(processMonitor, err) 
     }  
     processMonitor.Output = &output 
     processStateListener.OnComplete(processMonitor) 
    }() 
} 

The test process_test.go은 몇 가지 예를 보여줍니다

// Test case for fork 
func TestFork(t *testing.T) { 
    processStateListenerImpl := &ProcessStateListenerImpl{make(chan bool)} 
    Fork(processStateListenerImpl,"ls", "-a") //("ping","192.168.3.141","-c","3") 
    // waiting onto monitor 
    <-processStateListenerImpl.monitor 
} 
+0

그것은'ls' 과정을 포크합니다. 나는 내가 달리고있는 것과 동일한 과정을 포크로 만들고 싶다. 어떻게해야합니까 -'C++ '의'fork'? – Shashwat

+0

@Shashwat 확실하지 않음 : 나는 단지 반대쪽을 보았습니다 (http://stackoverflow.com/q/22805059/6309) – VonC

+0

저는 여기에 '추측합니다 :'return'누락 된'if err! = nil' 블록이 있습니다 '포크'의 –