Bagaimana cara copy-on-write di fork () menangani banyak fork?

23

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 execpanggilan sistem " " (yang digunakan untuk mengeksekusi file yang dapat dieksekusi dari dalam program C) atau keluar segera setelah fork(). Ketika anak diperlukan hanya untuk mengeksekusi perintah untuk proses induk, tidak perlu menyalin halaman proses induk, karena execmenggantikan 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?

ssgao
sumber
Wikipedia benar dalam hal ini, hanya level yang lebih tinggi.
Didi Kohen
1
Ya, salin saat menulis adalah penyalinan yang malas, proses anak salin halaman saat mencoba menulisnya. Jadi pada dasarnya, setelah garpu, memori anak hampir dibagikan dengan orang tua. Namun, sebelum proses apa pun dibuat, setiap proses anak masih memiliki memori pribadi, dimodifikasi dari alokasi orang tua atau baru. Itu berarti bahkan tanpa tindakan apapun proses anak bercabang memiliki memori pribadi. Kami dapat memverifikasinya dengan pmap -XX PIDatau cat /proc/PID/smap.
dimana23
Mengenai - "Halaman asli diberi tanda yang dapat ditulis setelahnya.", Siapa yang akan memilikinya? Sini proses lain yang belum mencoba menulisnya?
Adil
Ini indah. Mari kita mulai mengajarkan ini di taman kanak
ed22

Jawaban:

18

Tidak ada yang terjadi. Semua proses berbagi set halaman yang sama dan masing-masing mendapatkan salinan pribadi ketika ingin memodifikasi halaman.

Jlliagre
sumber
Kanan. Intinya adalah, proses anak yang khusus, yang memiliki tugas menyalin jika mencoba menulis ke halaman bersama. Baik orang tua maupun anak-anak lain tidak perlu tahu tentang perubahan jika dilakukan dengan benar.
Charles Stewart
9
Proses anak tidak begitu istimewa. Baik proses anak dan orang tua memiliki set halaman yang sama hanya untuk dibaca setelah garpu. Sejauh menyangkut halaman-halaman ini, penanganan halaman simetris.
jlliagre
3

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.

CyberFonic
sumber
0

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.

Didi Kohen
sumber
sistem mana yang melakukan ini? linux menggunakan implementasi copy-on-write
brauliobo
Begitulah cara copy-on-write bekerja ...
Didi Kohen
3
@ Davidviden bukan itu cara copy-on-write bekerja dalam versi apa pun yang pernah saya dengar. Tidak ada proses "master". Jika ada satu proses menulis halaman yang dibagikan, salinannya akan terbentur ke proses pribadi sementara semua proses lainnya terus membagikannya.
Celada
1
Saya pikir David Kohen benar dalam beberapa hal. Ini adalah salah satu cara untuk mengimplementasikan copy-on-write. Intinya adalah bahwa dengan penandaan ini, menulis ke halaman itu akan memicu penangan kesalahan halaman yang kemudian akan mengambil tindakan yang tepat, yaitu copy-on-write. Sayangnya detail ini (yang akan spesifik sistem) sebagian besar tidak relevan untuk pertanyaan. Perlu diingat bahwa Kontrak Karya memiliki dua dimensi: yang terlihat untuk proses dan yang bagaimana kernel dapat mengimplementasikannya.
0xC0000022L