Ich möchte einen Go-Prozess abzweigen und die ID des neuen Prozesses zurückbekommen, aber alles, was ich in den exec
oder os
Bibliotheken sehen kann, ist einen neuen Prozess zu starten.Wie mache ich einen Go-Prozess?
Antwort
Sie wollen angeblich syscall.ForkExec()
vom syscall
Paket.
Beachten Sie, dass fork()
zu der Zeit erfunden wurde, als überhaupt keine Threads verwendet wurden, und ein Prozess hatte immer nur einen einzigen Thread der Ausführung in sich, und daher war die Verzweigung sicher. Mit Go ist die Situation radikal anders, da es in hohem Maße Threads auf Betriebssystemebene verwendet, um die Routineplanung zu beschleunigen.
Nun schmucklos fork(2)
auf Linux wird das Kind Prozess machen müssen nur die einzelnen Thread — derjenige, der fork(2)
in den übergeordneten Prozess — unter all diejenigen genannt, die aktiv waren, darunter auch einige wichtige Themen von der Go-Laufzeit verwendet. Im Grunde bedeutet dies, dass Sie einfach nicht erwarten können, dass das Kind process in der Lage sein wird, weiterhin Go-Code, auszuführen, und das einzige, was Sie sinnvollerweise tun können, ist, sofort durchzuführen exec(2)
. Beachten Sie, dass syscall.ForkExec()
für verwendet wird.
Und nun über das Problem weiter denken. Ich würde sagen, in diesen Tagen die einzige Sache, die ein direkter Anruf zu fork(2)
ist nützlich für "best-work asynchronen Prozess State Snapshotting" — der Art, sagen Redis verwendet. Diese Technik beruht auf der Tatsache, dass der Kindprozess alle Speicherdatenseiten von seinem Elternteil erbt, aber das Betriebssystem verwendet die Copy-on-Write-Technik, um nicht wirklich alle Daten zu kopieren, so dass das Kind einfach dort sitzen und alle Datenstrukturen speichern kann auf Platte, während sein Elternteil weg tuckert und sie in seinem eigenen Adressraum ändert. Jede andere denkbare Verwendung für fork()
impliziert sofortige exec()
, und das ist, was exec.Command()
et al ist, warum also einfach nicht verwenden?
Eine Lösung ist die Verwendung einer exec.Command
in ihrer Goroutine ausgeführt.
Das ist, was das kleine Projekt akshaydeo/go_process
tut:
// 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
zeigt einige Beispiele:
// 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
}
Es ist Forking 'ls' Prozess. Ich möchte den gleichen Prozess forkieren, den ich gerade betreibe. Wie kann ich das tun - 'Gabelung von' C++ '? – Shashwat
@Shashwat nicht sicher: Ich habe nur das Gegenteil gesehen (http://StackOverflow.com/q/22805059/6309) – VonC
Ich rate hier: Es gibt eine 'Rückkehr' fehlt im' if err! = Nil' Block von 'Gabel'. –
- 1. Wie mache ich einen Bildkonverter?
- 2. Wie mache ich einen Slider wie Javascript?
- 3. Wie mache ich einen "verzweigten" Conduit?
- 4. Wie mache ich einen (statischen) Initialisiererblock strictfp?
- 5. Wie mache ich einen Einsatz mit einem
- 6. Wie mache ich einen Ordner/Verzeichnis
- 7. Wie mache ich einen Clip (LIDAR-Daten)
- 8. Wie mache ich einen Text als auswählbar?
- 9. Wie mache ich einen Befehlszeilen-Texteditor?
- 10. Wie mache ich einen "zurück" -Link?
- 11. Wie mache ich einen MdiClient-Hintergrund transparent?
- 12. Wie mache ich einen Datumsvergleich in Javascript?
- 13. Wie mache ich einen Piepton in Android?
- 14. Wie mache ich einen Link in Javascript
- 15. Wie mache ich einen runden Fortschrittsbalken?
- 16. Wie mache ich einen animierten Spritekit-Hintergrund?
- 17. Wie mache ich einen Git Push?
- 18. AngularJS: Wie mache ich einen schwankenden Fortschrittsbalken?
- 19. Wie mache ich einen Zeilenumbruch in Python?
- 20. Wie mache ich einen aktiven Schlaf?
- 21. Wie mache ich einen QVector von Widgets?
- 22. Wie mache ich einen "Screenshot" eines NSView?
- 23. Wie mache ich einen Schlaf in Javascript?
- 24. Wie mache ich einen Feld Autofokus?
- 25. Wie mache ich einen Kohlezeichnung Filter
- 26. Wie mache ich einen androiden Button?
- 27. Wie mache ich Hintergrundcode?
- 28. Wie mache ich Konfetti?
- 29. Wie mache ich einen neuen Tab wie Fehler in Eclipse
- 30. Wie mache ich einen Fortschritt Button wie folgt für Android?
"Jede andere denkbare Verwendung von fork() impliziert sofortiges exec(), und dafür ist exec.Command() et al. Warum also einfach nicht verwenden?" Es gibt setrlimit(), das Einrichten von SELinux, chroot() ing, das Schließen oder Einrichten von FDs vor der Übergabe der Kontrolle - und das muss zwischen fork() und exec() passieren, nein? –
Was ist, wenn "Best-Effort asynchrone Prozessstatus-Snapshotting" * genau * ist, was ich versuche zu tun? – cpcallen
@cpcallen, ich fürchte, das wäre "nicht in Go" * so. * Das Problem ist, dass die Go-Laufzeit zwei Dinge zu den OS-Level-Threads macht: a) verwendet sie, um Ihre Goroutines anzutreiben ; b) benutzt sie für ihre eigenen Bedürfnisse.Da nur ein einziger Thread eine 'fork()' überlebt, wird er, sobald er in einem neuen Prozess wieder aufgenommen wird, in einem halb-assestierten Zustand sein, was unmöglich ist, richtig zu arbeiten. – kostix