Was ist der Unterschied zwischen der Verwendung von _exit() und exit() in einer herkömmlichen Linux-Fork-Exec?

Lesezeit: 4 Minuten

Benutzeravatar von ned1986zha
ned1986zha

Ich habe versucht herauszufinden, wie der Fork-Exec-Mechanismus in Linux verwendet wird. Alles lief nach Plan, bis mich einige Webseiten zu verwirren begannen.

Es wird gesagt, dass ein untergeordneter Prozess unbedingt verwendet werden sollte _exit() statt einfach exit() oder eine normale Rückkehr von main().

Wie ich weiß, führt die Linux-Shell jeden externen Befehl aus; Unter der Annahme, dass das, was ich oben gesagt habe, wahr ist, lautet die Schlussfolgerung, dass keiner dieser externen Befehle oder irgendeine andere Ausführung, die innerhalb der Linux-Shell stattfindet, eine normale Rückkehr bewirken kann!

Wikipedia und einige andere Webseiten behaupten, dass wir sie verwenden müssen _exit() Nur um zu verhindern, dass ein untergeordneter Prozess die temporären Dateien des übergeordneten Prozesses löscht, während ein wahrscheinliches doppeltes Leeren der stdio-Puffer auftreten kann. Obwohl ich Ersteres verstehe, habe ich keine Ahnung, wie ein doppeltes Leeren von Puffern für ein Linux-System schädlich sein könnte.

Ich habe meinen ganzen Tag damit verbracht … Danke für jede Klarstellung.

  • Duplikat von stackoverflow.com/questions/2329640/… . Auch verwandt: stackoverflow.com/questions/3657667/exit-functions-in-c

    – Adam Rosenfield

    25. März 2011 um 5:26 Uhr

Benutzeravatar von Fred Foo
Fred Fu

Du solltest benutzen _exit (oder sein synonym _Exit), um das untergeordnete Programm abzubrechen, wenn die exec schlägt fehl, da in dieser Situation der untergeordnete Prozess die externen Daten (Dateien) des übergeordneten Prozesses stören kann, indem er seine aufruft atexit Handler, Aufrufen seiner Signal-Handler und/oder Leeren von Puffern.

Aus dem gleichen Grund sollten Sie auch verwenden _exit in jedem untergeordneten Prozess, der keine ausführt execaber die sind selten.

In allen anderen Fällen einfach verwenden exit. Wie Sie teilweise selbst bemerkt haben, jeder Prozess in Unix/Linux (außer einem, init) ist das Kind eines anderen Prozesses, also using _exit in jedem untergeordneten Prozess würde das bedeuten exit ist außerhalb nutzlos init.

switch (fork()) {
  case 0:
    // we're the child
    execlp("some", "program", NULL);
    _exit(1);  // <-- HERE
  case -1:
    // error, no fork done ...
  default:
    // we're the parent ...
}

  • Tonnen von Dank. Ich fühle mich jetzt viel besser; Obwohl das zweimalige Spülen eines Puffers immer noch problematisch ist, hat es für mich keine Bedeutung.

    – ned1986zha

    24. März 2011 um 18:11 Uhr

  • @ned1986zha: Zum Zeitpunkt des fork(), können sich Daten in den stdio-Puffern befinden. Wenn sowohl der übergeordnete als auch der untergeordnete Puffer diese Puffer leeren, erscheinen diese Daten zweimal in der Ausgabe. Das Problem besteht nicht, wenn exec() erfolgreich, da in diesem Fall der neu ausgeführte Prozess mit frischen stdio-Pufferspeichern beginnt.

    – Café

    24. März 2011 um 22:10 Uhr

  • @ned1986zha: Ja – die stdio Buffer ist ein C-Bibliotheksmechanismus. Es kann auch eine vom Betriebssystem bereitgestellte Pufferung geben – aber das spielt keine Rolle, da die fork() wird das nicht duplizieren.

    – Café

    25. März 2011 um 8:30 Uhr

  • @Bin: Wie die Kommentare oben sagen, _exit() stellt sicher, dass die Puffer auf C-Bibliotheksebene (userspace stdio) nicht geleert werden, da diese Puffer dupliziert werden fork() (da sie Userspace sind, sind sie dem Kernel nicht bekannt). Alle Puffer auf Kernel-Ebene würden immer noch geleert, aber das ist in Ordnung, da Puffer auf Kernel-Ebene nicht dupliziert werden fork().

    – Café

    26. Juli 2016 um 0:13 Uhr

  • @Bin: Wenn der Prozess vom Kernel beendet wird, werden die Dateideskriptoren geschlossen, aber die stdio-Puffer werden nicht geleert – da der Kernel nichts über diese Puffer weiß, sind sie vollständig eine Kreation der Userspace-C-Bibliothek.

    – Café

    26. Juli 2016 um 13:56 Uhr

Benutzeravatar von Nandan Bharadwaj
Nandan Bharadwaj

exit() löscht io-Puffer und führt einige andere Dinge aus, z. B. das Ausführen von Funktionen, die von registriert wurden atexit(). exit() ruft _end( )

_exit() beendet einfach den Prozess, ohne dies zu tun. Du rufst an _exit() vom übergeordneten Prozess, wenn Sie beispielsweise einen Daemon erstellen.

Bemerke das schon mal main() ist eine Funktion? Haben Sie sich jemals gefragt, wie es überhaupt hieß? Wenn ein ac-Programm ausgeführt wird, stellt die Shell, in der Sie ausgeführt werden, den ausführbaren Pfad zum Systemaufruf „exec“ bereit, und die Steuerung wird an den Kernel übergeben, der wiederum die Startfunktion jeder ausführbaren Datei aufruft _start()ruft deine an main()Wenn main() gibt es zurück und ruft dann an _end() Einige Implementierungen von C verwenden leicht unterschiedliche Namen für _end() & _start()

exit() und _exit() aufrufen _end()

Normalerweise – für jeden main() es sollte eins und nur eins geben exit() Anruf. (oder zurück am Ende von main() )

exit() befindet sich oben auf _exit() und verwendet eine herkömmliche C-Bibliothek.

Da sind die Unterschiede:

  1. _exit() leert den stdio-Puffer nicht, während exit() den stdio-Puffer vor dem Beenden leert.

  2. _exit() kann keinen Bereinigungsprozess durchführen, während exit() mit irgendeiner Funktion (dh on_exit oder at_exit) registriert werden kann, um einen Bereinigungsprozess durchzuführen, falls irgendetwas erforderlich ist, bevor das Programm existiert.

exit(status) übergibt einfach den Exit-Status an _exit(status). Es wird empfohlen, immer dann, wenn Sie fork() ausführen, einen von ihnen zwischen Kind und Eltern, einen _exit() und einen anderen exit() zu verwenden.

Im untergeordneten Zweig von a fork()es ist normalerweise falsch zu verwenden
exit()da dies dazu führen kann, dass stdio-Puffer geleert werden zweimalund temporäre Dateien werden unerwartet entfernt.

Auszug aus: http://www.unixguide.net/unix/programming/1.1.3.shtml

1415450cookie-checkWas ist der Unterschied zwischen der Verwendung von _exit() und exit() in einer herkömmlichen Linux-Fork-Exec?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy