Apakah fork () segera menyalin seluruh tumpukan proses di Linux?

30

Sebuah fork()system call klon proses anak dari proses yang berjalan. Kedua proses identik kecuali untuk PID mereka.

Tentu saja, jika prosesnya hanya membaca dari tumpukan mereka daripada menulis ke sana, menyalin tumpukan itu akan membuang-buang memori.

Apakah seluruh proses tumpukan disalin? Apakah dioptimalkan sedemikian rupa sehingga hanya tulisan yang memicu salinan tumpukan?

Adam Matan
sumber

Jawaban:

19

The keseluruhan dari fork()diimplementasikan menggunakan mmap / menyalin pada menulis.

Ini tidak hanya memengaruhi tumpukan, tetapi juga berbagi perpustakaan, tumpukan, area BSS.

Yang, kebetulan, berarti garpu adalah operasi yang sangat ringan, sampai 2 proses yang dihasilkan (orang tua dan anak) benar-benar mulai menulis ke rentang memori. Fitur ini adalah kontributor utama dari mematikan bom fork - Anda berakhir dengan terlalu banyak proses sebelum kernel menjadi kelebihan dengan replikasi dan diferensiasi halaman.

Anda akan kesulitan menemukan di OS modern contoh operasi di mana kernel melakukan hard copy (pengecualian driver perangkat) - hanya jauh, lebih mudah dan lebih efisien untuk menggunakan fungsionalitas VM.

Bahkan execve()pada dasarnya adalah "tolong mmap binary / ld.so / yang lainnya, diikuti dengan eksekusi" - dan VM menangani pemuatan aktual dari proses ke RAM dan eksekusi. Variabel tak diinisialisasi lokal berakhir dengan mmaped dari 'nol-halaman' - halaman read-only copy-on-write khusus yang mengandung nol, variabel inisialisasi lokal akhirnya menjadi mmaped (copy-on-write, lagi) dari file biner itu sendiri, dll.

qdot
sumber
Satu pengecualian penting adalah proses Java. Cari "fork java memory" dan Anda akan menemukan lusinan masalah yang mempengaruhi JVM server besar atau JVM tertanam yang mencoba mengeksekusi perintah shell kecil dan secara tidak sengaja menabrak pengecualian "Tidak dapat mengalokasikan memori" (ini hanya tautan acak, masalah ini bersifat sistemik ke lingkungan Java). Jawaban SO ini menuduh pengumpul sampah & kompiler JIT JVM menjaga agar proses memori tidak dibagikan.
WhiteWinterWolf
24

Kernel Linux tidak mengimplementasikan Copy-on-Write saat fork()dipanggil. Ketika syscall dijalankan, halaman yang dibagikan oleh orang tua dan anak ditandai hanya-baca.

Jika penulisan dilakukan pada halaman read-only, maka itu akan disalin, karena memori tidak lagi identik antara kedua proses. Oleh karena itu, jika hanya operasi baca yang dilakukan, halaman tidak akan disalin sama sekali.

mmk
sumber
1
+1 Terima kasih! 1. Bisakah Anda memberikan tautan referensi? 2. Apakah tumpukan disalin seluruhnya, atau sebagian?
Adam Matan
4
2. - Dalam halaman :) Kernel memiliki sedikit pemahaman tentang apa "heap" itu - untuk kernel, itu hanya sekelompok halaman pribadi yang di-mmapped, yang ditangani oleh libc pengalokasi sesuai keinginannya.
qdot
Apakah ini benar-benar bom fork? Tampaknya bagi saya bahwa alih-alih mengambil proses saat ini, kode ini akan membuat lebih banyak contoh dari program yang sama yang dijalankan dari awal daripada dari instruksi berikutnya setelah fork()panggilan.
sherrellbc
@mmk FYI, saya cukup terkejut dengan "Catatan menarik:" Anda dan saya menguji (di Linux 3.2.0) untuk melihat, dan sepertinya tidak benar. Saya biasa /proc/self/pagemapmenentukan alamat virtual untuk pemetaan halaman fisik untuk keperluan tes. Seperti yang saya harapkan, jika cucu dan hanya cucu yang menulis halaman bersama, maka orang tua dan anak asli terus membagikannya. Hanya cucu yang berakhir dengan salinan pribadi.
Celada
@Celada. Hmm. Saya telah membaca ini di suatu tempat, dan saya tidak ingat versi kernel yang dimaksud (mungkin yang lebih tua?), Jadi, itu mungkin tidak lagi valid.
mmk
10

Linux melakukan Copy-on-Write. Saat forkmembuat proses baru, halaman yang dialokasikan ditandai sebagai hanya dapat dibaca dan dibagikan antara orang tua dan anak. Ketika salah satu dari mereka mencoba untuk memodifikasi halaman, kesalahan halaman dihasilkan menghasilkan menyalin halaman dan menyesuaikan tabel halaman dengan tepat.

unxnut
sumber