Voglio avviare un processo di go e recuperare l'id dei nuovi processi, ma tutto quello che posso vedere nelle librerie exec
o os
è avviare una nuova procedura.Come si esegue il fork di un processo go?
risposta
È presumibilmente vogliono syscall.ForkExec()
dal pacchetto syscall
.
Si noti che fork()
è stato inventato nel momento in cui non sono stati utilizzati affatto thread e un processo aveva sempre avuto solo un singolo thread di esecuzione in esso, e quindi la creazione di un fork era sicuro. Con Go, la situazione è radicalmente diversa in quanto utilizza intensamente thread a livello di sistema operativo per alimentare la sua pianificazione di goroutine.
Ora, disadorno fork(2)
su Linux farà il processo figlio ha solo il singolo thread — quella che chiama fork(2)
nel processo padre — tra tutte quelle che erano attivi, tra cui alcune discussioni cruciali utilizzati dal runtime Go. Fondamentalmente questo significa che semplicemente non può aspettarsi che il figlio procss sia in grado di continuare a eseguire il codice Go, e l'unica cosa che si può sensibilmente fare è in qualche modo eseguire immediatamente exec(2)
. Si noti che questo è ciò per cui è previsto l'uso di syscall.ForkExec()
.
E ora pensa al problema ulteriormente. In questi giorni direi che l'unica cosa che una chiamata diretta a fork(2)
è utile per "lo snapshot dello stato del processo asincrono best-effort" — per il tipo, ad esempio, Redis. Questa tecnica si basa sul fatto che il processo figlio eredita tutte le pagine di dati di memoria dal suo genitore, ma il sistema operativo usa la tecnica copy-on-write per non copiare veramente tutti quei dati, così il bambino può semplicemente sedersi e salvare tutte le strutture dati su disco mentre il suo genitore sta scompigliando modificandoli nel proprio spazio indirizzo. Ogni altro uso concepibile per fork()
implica l'immediato exec()
, ed è per questo che è exec.Command()
et al, quindi perché non usarlo?
Una soluzione è utilizzare un exec.Command
eseguito nella sua goroutine.
Questo è quello che il piccolo progetto akshaydeo/go_process
fa:
// 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
mostra alcuni esempi:
// 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
}
Si sta creando un processo 'ls'. Voglio dare lo stesso processo che sto eseguendo. Come posso farlo - 'fork' di' C++ '? – Shashwat
@Shashwat non sono sicuro: ho visto solo il contrario (http://stackoverflow.com/q/22805059/6309) – VonC
Sto indovinando qui: c'è un 'return' mancante nel blocco' if err! = Nil' di 'Fork'. –
- 1. Processo di fork di Golang
- 2. Come si esegue exec() un processo in background in C?
- 3. Come restituisce fork() per il processo figlio
- 4. Come si esegue il test dell'unità clojure.core.async go macro?
- 5. Impossibile `syscall.Kill()` un processo Go daemonized
- 6. UnicodeEncodeError solo quando si esegue come un processo di cron
- 7. iPhone e Ipad: come si esegue il fork di un codice?
- 8. Impossibile allocare memoria: fork: impossibile eseguire il fork di un nuovo processo?
- 9. Processo di fork con CC .NET
- 10. Come si esegue il pacchetto di ritardo App Engine Go SDK su un modulo diverso?
- 11. Come posso scaricare tutti gli stack di un processo Go?
- 12. gdb debug del processo figlio dopo il fork (modalità figlio in modalità follow-fork configurata)
- 13. Come si esegue il test del codice dell'unità che crea un nuovo processo?
- 14. Come si esegue il debug di AppleScript?
- 15. Python verifica se un processo fork() è terminato
- 16. Alternativa per spawnare un processo con 'fork' in jRuby?
- 17. Processo figlio fork con timeout e output di acquisizione
- 18. fork() - più chiamate di sistema e di processo
- 19. Go esegue correttamente il marshal float64 su JSON?
- 20. Come si esegue il debug in un assembly ILMerged?
- 21. Come si esegue il downgrade di un pacchetto Chocolatey?
- 22. Come si esegue il ciclo di un array multidimensionale?
- 23. Come si esegue il backup di un pacchetto SalesForce?
- 24. Come si esegue il debug di un POST webhook?
- 25. Come si esegue il debug di un contenitore Unity "Resolve"?
- 26. Come si esegue il rendering di un triangolo in QOpenGLWidget?
- 27. Come si esegue il commit di un tag git?
- 28. Come si manifesta un processo di zombi?
- 29. Come si esegue il mio server bower
- 30. Come rintracciare lo script PHP che esegue un determinato processo?
"Ogni altro uso concepibile per fork() implica exec immediato(), ed è per questo che exec.Command() et al è, quindi perché non usarlo?" C'è setrlimit(), impostazione di SELinux, chroot() ing, chiusura o impostazione di FDs prima di passare il controllo - e questi devono avvenire tra fork() ed exec(), no? –
E se "lo snapshot dello stato del processo asincrono best-effort" è * precisamente * cosa sto cercando di fare? – cpcallen
@cpcallen, temo, sarebbe "not in go" * in questo modo. * L'essenza del problema è che il runtime di Go fa due cose ai thread a livello di sistema operativo: a) li usa per alimentare le tue goroutine ; b) li usa per i propri bisogni.Poiché solo un singolo thread sopravvive a un fork() ', non appena viene ripreso in un nuovo processo, sarà in uno stato semi-assed, impossibile da funzionare correttamente. – kostix