Mengapa anak dari vfork atau fork memanggil _exit () alih-alih keluar ()?

12

Dari halaman manual dari vfork():

vfork () berbeda dari fork () karena orangtua ditangguhkan hingga anak melakukan panggilan untuk mengeksekusi (2) atau _exit (2). Anak berbagi semua memori dengan induknya, termasuk tumpukan, sampai execve () dikeluarkan oleh anak. Anak tidak boleh kembali dari fungsi saat ini atau panggilan keluar (), tetapi dapat memanggil _exit ().

Mengapa anak harus menggunakan _exit()panggilan telepon daripada hanya menelepon exit()? Saya harap ini berlaku untuk keduanya vfork()dan fork().

Sen
sumber
2
jika Anda tertarik pada diskusi
xenoterracide

Jawaban:

11

Seperti yang terlihat sebelumnya , vforktidak memungkinkan proses anak untuk mengakses memori orang tua. exitadalah fungsi pustaka C (itulah sebabnya sering ditulis sebagai exit(3)). Ia melakukan berbagai tugas pembersihan seperti pembilasan dan penutupan stream C (file yang dibuka melalui fungsi yang dinyatakan dalam stdio.h) dan menjalankan fungsi yang ditentukan pengguna yang terdaftar atexit. Semua tugas ini melibatkan membaca dan menulis ke memori proses.

_exitkeluar tanpa pembersihan. Ini secara langsung pemanggilan sistem (itulah sebabnya itu ditulis sebagai _exit(2)), biasanya dilaksanakan dengan menempatkan nomor pemanggilan sistem dalam register prosesor dan menjalankan instruksi prosesor tertentu (bercabang ke pengendali panggilan sistem). Ini tidak perlu mengakses memori proses, jadi aman untuk dilakukan setelahnya vfork.

Setelah itu fork, tidak ada batasan seperti itu: proses orangtua dan anak sekarang sepenuhnya otonom.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
vfork tidak mengizinkan proses anak mengakses memori orang tua ? Tapi saya pikir mereka berbagi ruang alamat yang sama, sehingga anak dapat mengakses ruang alamat orang tua. Apakah pemahaman itu salah?
Sen
Setelah bercabang, tidak ada batasan seperti itu: proses orangtua dan anak sekarang sepenuhnya otonom. Apakah itu berarti saya dapat memanggil pintu keluar () dari anak garpu?
Sen
1
@ Sen: Anak tidak diizinkan mengakses memori orang tua. Jika Anda mencobanya, mungkin berhasil, karena kernel tidak akan melindungi Anda. Tetapi efeknya mungkin bukan apa yang Anda inginkan; misalnya, jika kompiler Anda memutuskan untuk meninggalkan beberapa nilai dalam register, itu tidak akan terlihat oleh proses induk.
Gilles 'SANGAT berhenti menjadi jahat'
@ Sen: Setelah melakukan fork, Anda dapat melakukan panggilan keluar atau fungsi lainnya. Setiap proses dimulai setelah garpu (di Linux, bahkan proses awal initbercabang oleh kernel).
Gilles 'SANGAT berhenti menjadi jahat'
3

exitlakukan pembersihan tambahan seperti fungsi panggilan yang didaftarkan oleh atexitkarena itu mengakses data di luar bagian yang disalin. _exitmelakukan syscall secara langsung tanpa pembersihan apa pun kecuali dalam kernel.

Maciej Piechotka
sumber
... dan perlu dicatat bahwa fork () benar-benar menyalin semuanya, sehingga Anda mungkin dapat memanggil exit (), dan Anda pasti dapat kembali dari fungsi saat ini.
derobert
3

Anda memiliki panggilan anak _exit () untuk menghindari pembilasan stdio (atau lainnya) buffer ketika proses anak keluar. Karena proses anak merupakan salinan persis dari proses induk, proses anak masih memiliki apa pun yang dimiliki orang tua di "stdout" atau "stderr", buffer dari <stdio.h>. Anda dapat (dan akan, pada waktu yang tidak tepat) mendapatkan output ganda dengan memanggil exit (), satu dari child process 'atexit handler, dan satu dari parent, ketika buffer dalam proses parent menjadi penuh, dan mendapatkan flush.

Saya menyadari jawaban di atas berkonsentrasi pada stdio.h spesifik, tetapi gagasan itu mungkin mengarah ke I / O buffered lainnya, seperti yang ditunjukkan oleh salah satu jawaban di atas.

Bruce Ediger
sumber
1

exit(): - melakukan beberapa tugas pembersihan, seperti menutup aliran i / o dan banyak lagi, lalu kembali ke kernel. _exit(): - langsung datang ke kernel (tidak melakukan tugas pembersihan).

fork() : kedua orang tua dan anak memiliki tabel file yang berbeda, sehingga perubahan yang dilakukan oleh anak tidak mempengaruhi parameter lingkungan dari orang tua, dan sebaliknya.

vfork(): baik induk maupun anak menggunakan tabel file yang sama, sehingga perubahan yang dilakukan oleh anak mempengaruhi parameter lingkungan induk. misalnya beberapa variabel var=10, sekarang dijalankan var++oleh child dan kemudian jalankan parent, Anda dapat melihat efeknya var++pada output parent juga.

Seperti yang saya katakan jika Anda menggunakan exit()dalam vfork()maka semua i / o sudah ditutup. Jadi, bahkan jika orangtua berjalan dengan benar, Anda tidak bisa mendapatkan output yang tepat, karena semua variabel memerah dan semua aliran ditutup.

pengguna2670535
sumber