Apa yang terjadi ketika file dengan 100% halaman dalam cache halaman diubah oleh proses lain


14

Saya tahu bahwa ketika halaman cache halaman diubah, itu ditandai kotor dan memerlukan penulisan kembali, tetapi apa yang terjadi ketika:

Skenario: File / apps / EXE, yang merupakan file yang dapat dieksekusi, di-paging ke halaman cache sepenuhnya (semua halamannya ada di cache / memori) dan dijalankan oleh proses P

Rilis berkelanjutan kemudian menggantikan / apps / EXE dengan executable baru.

Asumsi 1: Saya berasumsi bahwa proses P (dan siapa pun dengan deskriptor file yang mereferensikan yang dapat dieksekusi) akan terus menggunakan yang lama, di memori / apps / EXE tanpa masalah, dan setiap proses baru yang mencoba mengeksekusi jalur itu akan mendapatkan executable baru.

Asumsi 2: Saya berasumsi bahwa jika tidak semua halaman file dipetakan ke dalam memori, semuanya akan baik-baik saja sampai ada kesalahan halaman yang membutuhkan halaman dari file yang telah diganti, dan mungkin akan terjadi segfault?

Pertanyaan 1: Jika Anda meng-mlock semua halaman file dengan sesuatu seperti vmtouch apakah itu mengubah skenario sama sekali?

Pertanyaan 2: Jika / apps / EXE berada pada NFS jarak jauh, apakah itu akan membuat perbedaan? (Saya kira tidak)

Harap perbaiki atau validasikan 2 asumsi saya dan jawab 2 pertanyaan saya.

Mari kita asumsikan ini adalah kotak CentOS 7.6 dengan semacam kernel 3.10.0-957.el7

Pembaruan: Memikirkan lebih jauh, saya ingin tahu apakah skenario ini tidak berbeda dengan skenario halaman kotor lainnya ..

Saya kira proses yang menulis biner baru akan membaca dan mendapatkan semua halaman cache karena semuanya dipetakan, dan kemudian semua halaman itu akan ditandai kotor. Jika mereka di-mlock, mereka hanya akan menjadi halaman tidak berguna yang menempati memori inti setelah hitungan ref menjadi nol.

Saya curiga ketika program yang saat ini dijalankan berakhir, apa pun akan menggunakan biner baru. Dengan asumsi itu semua benar, saya kira itu hanya menarik ketika hanya beberapa file yang di-paging.


Hanya untuk membuatnya jelas, mengganti file tidak akan menjadi hal yang besar (tergantung pada apakah dibuka kembali oleh aplikasi dan bagaimana aplikasi bereaksi terhadap konten yang dimodifikasi), tetapi memodifikasi file mmaped dapat membuat aplikasi crash parah (itu adalah masalah umum di dunia java ketika file zip yang memiliki entri direktori mmaped diubah). Namun itu tergantung pada platform, tidak dijamin bahwa wilayah mmaped melihat perubahan atau tidak.
eckes

Jawaban:


12

Rilis berkelanjutan kemudian menggantikan / apps / EXE dengan executable baru.

Ini bagian yang penting.

Cara file baru dirilis adalah dengan membuat file baru (misalnya /apps/EXE.tmp.20190907080000), menulis konten, mengatur izin dan kepemilikan dan akhirnya mengubah nama (2) menjadi nama akhir /apps/EXE, menggantikan file lama.

Hasilnya adalah bahwa file baru memiliki nomor inode baru (yang berarti, pada dasarnya, ini file yang berbeda.)

Dan file lama memiliki nomor inode sendiri, yang sebenarnya masih ada meskipun nama file tidak menunjuk ke sana lagi (atau tidak ada nama file yang menunjuk ke inode itu lagi.)

Jadi, kuncinya di sini adalah ketika kita berbicara tentang "file" di Linux, kita paling sering benar-benar berbicara tentang "inode" karena begitu file telah dibuka, inode adalah referensi yang kita simpan ke file tersebut.

Asumsi 1 : Saya berasumsi bahwa proses P (dan siapa pun dengan deskriptor file yang mereferensikan yang dapat dieksekusi) akan terus menggunakan yang lama, di memori / apps / EXE tanpa masalah, dan setiap proses baru yang mencoba mengeksekusi jalur itu akan mendapatkan executable baru.

Benar.

Asumsi 2 : Saya berasumsi bahwa jika tidak semua halaman file dipetakan ke dalam memori, semuanya akan baik-baik saja sampai ada kesalahan halaman yang membutuhkan halaman dari file yang telah diganti, dan mungkin akan terjadi segfault?

Salah. Inode lama masih ada, jadi kesalahan halaman dari proses menggunakan biner lama masih akan dapat menemukan halaman-halaman itu di disk.

Anda dapat melihat beberapa efek dari ini dengan melihat /proc/${pid}/exesymlink (atau, ekuivalen, lsofoutput) untuk proses yang menjalankan biner lama, yang akan menunjukkan /app/EXE (deleted)untuk menunjukkan nama tidak lagi ada tetapi inode masih ada.

Anda juga dapat melihat bahwa ruang disk yang digunakan oleh biner hanya akan dirilis setelah proses mati (dengan asumsi itu adalah satu-satunya proses dengan inode yang terbuka.) Periksa output dfsebelum dan setelah membunuh proses, Anda akan melihatnya turun sesuai ukuran biner tua yang Anda pikir tidak ada lagi.

BTW, ini tidak hanya dengan binari, tetapi dengan file yang terbuka. Jika Anda membuka file dalam suatu proses dan menghapus file, file tersebut akan disimpan pada disk hingga proses itu menutup file (atau mati.) Demikian pula dengan bagaimana hardlink menyimpan penghitung berapa banyak nama yang menunjuk ke inode dalam disk, driver filesystem (di kernel Linux) menyimpan konter dari berapa banyak referensi yang ada pada inode dalam memori , dan hanya akan melepaskan inode dari disk setelah semua referensi dari sistem yang berjalan telah dirilis juga.

Pertanyaan 1 : Jika Anda meng-mlock semua halaman file dengan sesuatu seperti vmtouch apakah itu mengubah skenario

Pertanyaan ini didasarkan pada asumsi 2 yang salah bahwa tidak mengunci halaman akan menyebabkan segfault. Tidak akan.

Pertanyaan 2 : Jika / apps / EXE berada pada NFS jarak jauh, apakah itu akan membuat perbedaan? (Saya kira tidak)

Ini dimaksudkan untuk bekerja dengan cara yang sama dan sebagian besar tidak, tetapi ada beberapa "gotcha" dengan NFS.

Kadang-kadang Anda dapat melihat artefak menghapus file yang masih terbuka di NFS (muncul sebagai file tersembunyi di direktori itu.)

Anda juga memiliki beberapa cara untuk menetapkan nomor perangkat ke ekspor NFS, untuk memastikan mereka tidak akan "diacak ulang" ketika server NFS reboot.

Tapi ide utamanya sama. Driver klien NFS masih menggunakan inode dan akan mencoba untuk menyimpan file (di server) saat inode masih dirujuk.


1
Apakah mengganti nama (2) memblokir sampai hitungan ref file oldname menjadi nol?
Gregg Leventhal

2
Tidak, ganti nama (2) tidak akan diblokir. Inode lama disimpan sekitar untuk waktu yang sangat lama.
filbranden

1
Lihat @ mosvy jawaban mengapa Anda tidak bisa menulis ke file yang dieksekusi (Anda mendapatkan ETXTBSY). Membatalkan tautan dan membuat yang baru memiliki efek nama yang sama: Anda berakhir dengan inode baru. (Ganti nama lebih baik karena dengan demikian tidak ada saat di mana nama file tidak ada, ini adalah operasi atom yang mengganti nama untuk menunjuk ke inode baru.)
filbranden

4
@GreggLeventhal: "Asumsi apa yang Anda buat tentang proses rilis berkelanjutan yang saya gunakan yang membuat Anda yakin itu menggunakan file sementara?" - Karena selama Unix ada, itu adalah dan telah menjadi satu-satunya cara yang waras untuk melakukannya. renamecukup banyak satu-satunya file dan filesystem operasi yang dijamin akan atom (dengan asumsi kita tidak lintas filesystem atau perangkat batas), jadi "membuat file temp dan kemudian rename" adalah yang pola standar untuk memperbarui file. Itu juga yang digunakan oleh setiap editor teks di Unix, misalnya.
Jörg W Mittag

1
@ grahamj42: renameadalah bagian dari POSIX. Memang, ini dimasukkan dengan mengacu pada ISO C (bagian 7.21.4.2 dalam konsep saat ini), tetapi ada di sana.
Jörg W Mittag

6

Asumsi 2: Saya berasumsi bahwa jika tidak semua halaman file dipetakan ke dalam memori, semuanya akan baik-baik saja sampai ada kesalahan halaman yang membutuhkan halaman dari file yang telah diganti, dan mungkin akan terjadi segfault?

Tidak, itu tidak akan terjadi, karena kernel tidak akan membiarkan Anda membuka untuk menulis ganti apa pun di dalam file yang sedang dijalankan. Tindakan seperti itu akan gagal dengan ETXTBSY[1]:

cp /bin/sleep sleep; ./sleep 3600 & echo none > ./sleep
[9] 5332
bash: ./sleep: Text file busy

Ketika dpkg, dll memperbarui biner, ia tidak menimpanya, tetapi menggunakan rename(2)yang hanya mengarahkan entri direktori ke file yang sama sekali berbeda, dan setiap proses yang masih memiliki pemetaan atau pegangan terbuka ke file lama akan terus menggunakannya tanpa masalah .

[1] perlindungan tersebut tidak diperluas ke file lain yang juga dapat dianggap "teks" (kode langsung / dapat dieksekusi): shared library, kelas java, dll; memodifikasi file seperti itu sementara dipetakan oleh proses lain akan menyebabkannya macet. Di linux, dynamic linker dengan patuh meneruskan MAP_DENYWRITEflag mmap(2), tetapi jangan salah - tidak ada efek apa pun.


1
Dalam skenario dpkg, pada titik manakah penggantian nama selesai sehingga dentry untuk / apps / EXE akan mereferensikan inode biner baru? Kapan tidak ada lagi referensi ke yang lama? Bagaimana cara kerjanya?
Gregg Leventhal

2
rename(2)adalah atom; segera setelah selesai, entri dir merujuk ke file baru. Proses yang masih menggunakan file lama pada saat itu hanya akan dapat mengaksesnya melalui pemetaan yang ada, atau melalui pegangan terbuka untuk itu (yang mungkin merujuk ke sebuah yatim piatu gigi, tidak lagi dapat diakses selain melalui /proc/PID/fd).
Mosvy

1
Saya suka jawaban Anda yang terbaik karena penyebutan ETXTBSY Anda membawa saya ke utcc.utoronto.ca/~cks/space/blog/unix/WhyTextFileBusyError ini yang menjawab semua pertanyaan saya.
Gregg Leventhal

4

jawaban filbranden benar dengan asumsi proses rilis kontinu melakukan penggantian atom file yang tepat via rename. Jika tidak, tetapi memodifikasi file di tempat, semuanya berbeda. Namun model mental Anda masih salah.

Tidak ada kemungkinan hal-hal yang dimodifikasi pada disk dan tidak konsisten dengan cache halaman, karena cache halaman adalah versi kanonik dan yang dimodifikasi. Setiap penulisan ke file dilakukan melalui cache halaman. Jika sudah ada di sana, halaman yang ada diubah. Jika belum ada, upaya untuk memodifikasi sebagian halaman akan menyebabkan seluruh halaman di-cache, diikuti oleh modifikasi seolah-olah itu sudah di-cache. Menulis bahwa span seluruh halaman atau lebih dapat (dan hampir pasti melakukan) mengoptimalkan langkah baca paging mereka. Dalam hal apapun, hanya ada satu versi yang dapat dimodifikasi kanonik file (*) yang pernah ada, yang ada di cache halaman .

(*) Saya sedikit berbohong. Untuk NFS dan sistem file jarak jauh lainnya, mungkin ada lebih dari satu, dan biasanya (tergantung yang mana dan opsi mount dan sisi-server mana yang digunakan) tidak menerapkan atomicity dan memesan semantik untuk penulisan dengan benar. Itu sebabnya banyak dari kita menganggap mereka rusak secara fundamental dan menolak menggunakannya untuk situasi di mana akan ada tulisan bersamaan dengan penggunaan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.