Kapan suatu proses garpu adalah virtual atau resident memory-nya disalin?

12

Cara standar untuk membuat proses baru di Linux adalah bahwa jejak memori dari proses induk disalin dan yang menjadi lingkungan proses anak sampai execvdipanggil.

Apa jejak memori yang kita bicarakan, virtual (apa proses yang diminta) atau yang residen (apa yang sebenarnya digunakan)?

Motivasi: Saya memiliki perangkat dengan ruang swap terbatas dan aplikasi dengan perbedaan besar antara jejak memori virtual dan penduduk. Aplikasi tidak dapat melakukan fork karena kekurangan memori dan ingin melihat apakah mencoba mengurangi ukuran tapak virtual akan membantu.

TheMeaningfulEngineer
sumber

Jawaban:

12

Dalam sistem modern tidak ada memori yang benar-benar disalin hanya karena panggilan sistem garpu digunakan. Itu semua ditandai hanya baca di tabel halaman sehingga pada upaya pertama untuk menulis jebakan ke dalam kode kernel akan terjadi. Hanya sekali proses proses pertama mencoba untuk menulis akan terjadi penyalinan.

Ini dikenal sebagai copy-on-write.

Namun mungkin perlu untuk melacak ruang alamat yang berkomitmen juga. Jika tidak ada memori atau swap tersedia pada saat kernel harus menyalin halaman, itu harus mematikan beberapa proses untuk membebaskan memori. Ini tidak selalu diinginkan, sehingga dimungkinkan untuk melacak berapa banyak memori yang telah dilakukan oleh kernel.

Jika kernel akan melakukan lebih dari memori + swap yang tersedia, itu dapat memberikan kode kesalahan saat mencoba memanggil fork. Jika cukup tersedia, kernel akan mengkomit ke ukuran virtual penuh dari induk untuk kedua proses setelah garpu.

kasperd
sumber
1
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.Ya terima kasih. Berarti bahwa mengurangi jejak virtual dari proses di lingkungan dengan memori terbatas (RAM dan swap) dapat memecahkan masalah tidak mampu melakukan fork.
TheMeaningfulEngineer
1
@Lan Ya. Jika forkgagal dengan pesan kesalahan yang menunjukkan memori tidak mencukupi. Kemudian mengurangi penggunaan proses memori virtual sebelum forking bisa membantu.
kasperd
5

Jangan khawatir, itu membuat salinan malas (copy-on-write). Alamat memori virtual dari kedua proses menunjuk ke halaman yang sama pada awalnya, tetapi ketika proses bercabang mencoba untuk memodifikasinya, sebenarnya membuat salinan fisik halaman (sejak saat itu, halaman itu berada di dua tempat di RAM Anda).

Hati-hati, tidak ada jejak memori yang dilaporkan yang benar-benar memberi tahu Anda berapa banyak RAM yang digunakan proses. Karena pertukaran, berbagi memori, dan masalah lain dengan memori virtual, mustahil untuk mengetahui dengan pasti. Beberapa bagian dari ruang memori adalah shared library (tempat menghitungnya?), Sebagian merujuk pada memori non-RAM (perangkat perangkat keras lainnya), ada yang saat ini ditukar, ada yang belum disalin (copy-on-write) dan begitu seterusnya. Baca ini:

https://lwn.net/Articles/642202/

orion
sumber
5

Ada pengaturan kernel

/ proc / sys / vm / overcommit_memory

Kutipan dari artikel luar biasa :

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

Ini berlaku untuk garpu dan juga malloc biasa. Yaitu jika Anda menetapkan ke 0, garpu akan disalin saat menulis. Salin saat menulis berarti bahwa sekali aplikasi bercabang dua, maka salinan itu akan berbagi halaman memori menggunakan anak atau asli mulai mengubah memori.

Dalam sebagian besar distribusi, saya tahu overcommit adalah 0. Tetapi jika Anda mengaturnya menjadi 2, semua halaman memori akan sepenuhnya didukung oleh memori nyata dan dalam beberapa kasus di bawah tekanan memori tinggi akan lebih stabil, tetapi beberapa program (saya menghadapi gitk) yang mengandalkan pada overcommits akan gagal.

gena2x
sumber