Menurut Wikipedia (yang bisa salah)
Ketika fork () panggilan sistem dikeluarkan, salinan dari semua halaman yang sesuai dengan proses induk dibuat, dimuat ke lokasi memori terpisah oleh OS untuk proses anak. Tetapi ini tidak diperlukan dalam kasus-kasus tertentu. Pertimbangkan kasus ketika seorang anak mengeksekusi
exec
panggilan sistem " " (yang digunakan untuk mengeksekusi file yang dapat dieksekusi dari dalam program C) atau keluar segera setelahfork()
. Ketika anak diperlukan hanya untuk mengeksekusi perintah untuk proses induk, tidak perlu menyalin halaman proses induk, karenaexec
menggantikan ruang alamat dari proses yang memanggilnya dengan perintah yang akan dieksekusi.Dalam kasus seperti itu, teknik yang disebut copy-on-write (COW) digunakan. Dengan teknik ini, ketika garpu terjadi, halaman proses induk tidak disalin untuk proses anak. Sebaliknya, halaman dibagi antara proses anak dan orang tua. Setiap kali suatu proses (orang tua atau anak) memodifikasi halaman, salinan terpisah dari halaman tertentu dibuat untuk proses tersebut (orang tua atau anak) yang melakukan modifikasi. Proses ini kemudian akan menggunakan halaman yang baru disalin daripada yang dibagikan di semua referensi di masa depan. Proses lain (yang tidak mengubah halaman bersama) terus menggunakan salinan asli halaman (yang sekarang tidak lagi dibagikan). Teknik ini disebut copy-on-write karena halaman disalin ketika beberapa proses menulis padanya.
Tampaknya ketika salah satu proses mencoba menulis ke halaman, salinan halaman baru akan dialokasikan dan ditugaskan untuk proses yang menghasilkan kesalahan halaman. Halaman asli ditandai setelah itu dapat ditulis.
Pertanyaan saya adalah: apa yang terjadi jika fork()
dipanggil berkali-kali sebelum ada proses yang mencoba menulis ke halaman bersama?
pmap -XX PID
ataucat /proc/PID/smap
.Jawaban:
Tidak ada yang terjadi. Semua proses berbagi set halaman yang sama dan masing-masing mendapatkan salinan pribadi ketika ingin memodifikasi halaman.
sumber
Perilaku fork () tergantung pada apakah sistem * nix memiliki MMU atau tidak. Pada sistem non-MMU (seperti PDP-11 awal) panggilan sistem garpu () menyalin semua memori orang tua untuk setiap anak. Pada sistem * nix berbasis MMU, kernel menandai semua halaman non-stack sebagai R / O dan membaginya antara induk dan anak. Kemudian ketika salah satu proses menulis ke halaman mana saja, MMU menjebak upaya tersebut, kernel kemudian mengalokasikan halaman yang dapat ditulisi dan memperbarui tabel-halaman MMU untuk menunjuk ke halaman yang sekarang dapat ditulis. Perilaku Copy-on-Write ini memberikan peningkatan sejak awalnya hanya stack pribadi yang perlu dialokasikan dan dikloning untuk setiap proses anak.
Jika Anda menjalankan beberapa kode induk antara setiap panggilan fork () maka proses anak yang dihasilkan akan berbeda dengan halaman yang telah diubah oleh orang tua. Di sisi lain, jika orang tua hanya mengeluarkan beberapa panggilan fork (), misalnya dalam satu lingkaran, maka proses anak akan hampir identik. Jika variabel loop lokal digunakan maka itu akan berbeda dalam tumpukan setiap anak.
sumber
Ketika sistem membentuk fork, biasanya (ini mungkin tergantung pada implementasi) ia juga menandai halaman sebagai read-only, dan menandai proses induk sebagai master dari halaman-halaman ini.
Ketika mencoba menulis ke halaman-halaman ini, kesalahan halaman terjadi dan OS mengambil alih, menyalin seluruh daftar halaman atau hanya yang diubah (sekali lagi, tergantung pada implementasi), sehingga proses penulisan akan memiliki salinan yang dapat ditulis.
Ketika ada beberapa proses bercabang dari yang sama, ketika proses "master" menulis ke memori itu, proses lain mendapatkan halaman yang setara disalin.
sumber