Bagaimana cara mengetahui apakah suatu file dipetakan dengan memori?

8

Saya bingung tentang file yang dipetakan memori, jadi saya punya beberapa pertanyaan yang saya akan sangat senang jika Anda dapat membantu saya.

  1. Katakanlah saya meramban direktori di sistem file saya dan ada file di direktori ini. Mungkinkah file ini menunjuk ke suatu wilayah di memori utama, alih-alih menunjuk ke suatu wilayah di disk?
  2. Jika ini mungkin, apakah ini yang kita sebut 'file yang dipetakan memori'?
  3. Apa artinya memindahkan file semacam itu di sekitar sistem file (yaitu, mvmemasukkan file seperti itu dari direktori ke direktori lain)? Apa yang saya pahami adalah, karena file tersebut dipetakan memori, proses (es) berinteraksi dengan file selalu menulis ke wilayah yang telah ditentukan dari memori utama, dan ketika kita membuka file itu (misalnya menggunakan vim), kita membaca wilayah itu dari utama memori (jadi, tidak ada disk yang terlibat). Karenanya, di mana pun kita memindahkan file, itu akan selalu berfungsi dengan benar, bukan? Jika ya, apakah memindahkan file di sekitar sistem file memiliki arti penting?
  4. Apakah ada perintah yang akan memberi tahu jika file dipetakan memori?
  5. Akhirnya, jika saya membuka file yang dipetakan dengan memori vim, buat beberapa perubahan padanya dan simpan dan tutup vim, apa yang akan terjadi? Apakah perubahan saya hanya akan ditulis ke memori utama? Jika demikian, apakah proses lain yang menggunakan file ini akan melihat perubahan yang baru saja saya buat? Dalam pengalaman saya, proses lain tidak melihat perubahan yang saya buat pada file ketika saya membuat beberapa perubahan pada file tersebut vim. Apa alasannya?
Utku
sumber
12
Ini mengingatkan saya pada seseorang yang bertanya bagaimana cara mengetahui apakah suatu file adalah tautan keras.
Dmitry Grigoryev
3
@DmitryGrigoryev Cukup lucu, pada kenyataannya, tetapi semua orang belajar :)
kucing

Jawaban:

24

File yang dipetakan dengan memori bekerja sebaliknya. Pemetaan memori bukan properti file, tetapi cara untuk mengakses file: suatu proses dapat memetakan konten file (atau subset daripadanya) ke dalam ruang alamatnya. Ini membuatnya lebih mudah untuk membaca dan menulis ke file; melakukannya hanya melibatkan membaca dan menulis dalam memori. File itu sendiri, pada disk, sama seperti file lainnya.

Untuk mengatur ini, proses menggunakan mmapfungsi. Ini juga dapat digunakan untuk tujuan lain, seperti berbagi memori antar proses.

Stephen Kitt
sumber
14
@Utku Ini tidak ada hubungannya dengan file yang dipetakan memori.
Satō Katsura
12
Jika Anda tidak mematikan server MySQL, itu perilaku normal: server memiliki deskriptor file terbuka pada file, dan itu tetap berlaku bahkan dengan mv.
Stephen Kitt
11
Deskriptor file menunjuk (akhirnya) ke inode di sistem file; di situlah file tersebut benar-benar hidup. Entri direktori juga menunjuk ke inode ini, dan mvhanya mengubah entri direktori, bukan inode (ketika memindahkan file pada sistem file yang sama).
Stephen Kitt
1
Deskripsi Anda adalah penyederhanaan yang berguna, tetapi hanya untuk akurasi: Pemetaan memori secara teknis tidak sama dengan deskriptor file, tetapi mereka bekerja dengan cara yang sama (dengan merujuk pada inode, bukan nama file). open (), mmap (), close () tidak meninggalkan FD, hanya pemetaan, yang akan muncul bersama lsof. Itu tidak hilang sampai proses memanggil munmap (), atau keluar (atau mengganti pemetaan dengan yang berbeda menggunakan mmap (MAP_FIXED) ...)
Peter Cordes
3
@ Utku Kamu tidak benar-benar memindahkan file. Anda baru saja membuat entri direktori baru yang merujuk ke file yang sama dan kemudian menghapus yang lama. Perubahan dalam penamaan tidak berpengaruh pada proses yang sudah membuka file.
David Schwartz
11

File yang dipetakan dengan memori tidak (harus) didukung oleh memori. Itu bisa dengan sempurna hidup di disk. Sebenarnya, di mana file tinggal bukan milik file itu sendiri tetapi dari sistem file itu berada.

Memetakan file dalam memori adalah operasi proses yang dapat dilakukan untuk memiliki sebagian file yang dimuat dalam memori. Hasilnya terlihat seperti wilayah memori biasa, kecuali ketika proses membaca dari atau menulis ke wilayah ini, itu sebenarnya membaca dari dan menulis ke file. Jika Anda membuka file, memetakannya ke memori, menulis ke sana dan menyimpannya, modifikasi akan dilakukan pada file, pada disk (jika itu hidup pada disk, tentu saja).

Ini dapat digunakan misalnya ketika Anda tahu harus Anda banyak akses untuk melakukan pada file, yang tidak akan berurutan, menjadi penyebabnya dapat lebih mudah dan lebih efisien untuk melakukan membaca dan menulis dalam memori daripada masalah read, write, dan llseekpanggilan sistem. Satu-satunya masalah dengan metode ini adalah Anda tidak dapat menggunakannya jika file perlu dibaca atau ditulis oleh beberapa proses secara bersamaan. Hasilnya tidak dapat diprediksi.

Saya tidak tahu perintah yang dapat memberi tahu Anda jika file saat ini dipetakan. Anda dapat memeriksa pemetaan suatu proses di /proc/<pid>/maps(jika sistem Anda memilikinya).

Untuk menjawab pertanyaan kedua Anda, ketika Anda membuka file, bahkan jika Anda memindahkannya di sistem file, proses yang telah dibuka masih dapat menggunakannya. Apa yang terjadi adalah file tidak tergantung dari entri di sistem file. Selama Anda memiliki file yang dibuka, Anda memiliki "pegangan", deskriptor file, yang memungkinkan Anda membaca dan menulis padanya, bahkan jika jalurnya dalam sistem file berubah. File menghilang hanya ketika tidak ada entri di sistem file dan tidak ada proses yang menyimpan deskriptor file di dalamnya.

lororget
sumber
Jadi, ketika kita memindahkan file, nilai deskriptor file tidak berubah. Ada pemetaan deskriptor jalur-ke-file dan hanya bagian jalur dari pemetaan yang berubah. Apakah ini benar?
Utku
1
Dalam beberapa hal ya, tapi saya tidak yakin untuk mengerti Anda, jadi saya ulangi. Pada dasarnya, "file" adalah tiga hal. Entri direktori adalah jalur di sistem file. Inode adalah konten file. Dan deskriptor file mewakili file terbuka. Entri direktori dan deskriptor file berisi pointer ke inode backing mereka. Ketika Anda membuka file, Anda melewati entri direktori dan kernel mengembalikan Anda deskriptor file. Jadi, bahkan jika entri direktori asli berubah, deskriptor file masih menunjuk ke inode yang sama, dan Anda dapat mengakses file.
lgeorget
1
Anda dapat memeriksa pemetaan suatu proses, dalam /proc/<pid>/maps. - Asalkan proses mengatakan hidup pada sistem yang memiliki /procuntuk memulai. OpenBSD tidak, dan FreeBSD sedang menghapusnya. Selain itu, FreeBSD telah /proc/<pid>/mapmenggantikan /proc/<pid>/maps.
Satō Katsura
@SatoKatsura Terima kasih atas ketepatannya. Saya hanya punya mesin Linux, jadi saya pikir saya akan memberi tahu tentang kasus saya dan membiarkan orang lain tahu tentangnya ... Jangan ragu untuk mengedit jawabannya jika ada yang perlu diperbaiki / tambahkan di sini.
lgeorget
Karena Anda bertanya: Anda menganggap OP benar-benar memahami apa yang dia minta, dan menjelaskan secara terperinci apa file yang dipetakan memori. Saya tidak berpikir Anda membuatnya menjadi layanan. IMO komentar pertama Anda di atas jauh lebih relevan dengan apa yang sebenarnya diminta oleh OP daripada jawaban Anda. FWIW.
Satō Katsura
9

T4: Apakah ada perintah yang akan memberi tahu jika suatu file dipetakan dengan memori?

The lsofperintah akan menampilkan semua file yang sedang digunakan oleh sistem. Kolom "FD" akan berisi "mem" jika file tersebut dipetakan memori. Jadi Anda bisa mendapatkan output dari perintah ini untuk nama file yang Anda minati.

Wossname
sumber
3
Atau gunakanlsof -ad mem /path/to/file
Stéphane Chazelas
5
Atau lebih tepatnya lsof -ad mem,txt /path/to/filesebagai file yang sedang dieksekusi juga memiliki sebagian dari mereka mmap di ruang alamat proses tetapi muncul seperti txtdalam lsofoutput.
Stéphane Chazelas
7

Anda tampaknya membingungkan pemetaan memori dengan file dalam sistem file yang berada di memori, bersama dengan konsep-konsep lain seperti bagaimana proses mempertahankan akses ke file bahkan ketika mereka dipindahkan.

Saya akan mengajukan pertanyaan demi pertanyaan untuk melihat apakah saya dapat menjelaskan semuanya.

  1. Katakanlah saya meramban direktori di sistem file saya dan ada file di direktori ini. Mungkinkah file ini menunjuk ke suatu wilayah di memori utama, alih-alih menunjuk ke suatu wilayah di disk?

Itu menunjuk ke memori utama jika itu pada sistem file yang berada di memori, seperti procfs yang biasanya dipasang di / proc, atau sysfs yang ada di / sys, atau tmpfs yang kadang-kadang ada di / tmp.

  1. Jika ini mungkin, apakah ini yang kita sebut 'file yang dipetakan memori'?

Tidak. Seperti yang dikatakan stephen-kitt, "pemetaan memori" mengacu pada cara untuk mengakses file dengan "memetakan" pada memori utama dan bekerja dengannya di sana daripada membaca dan menulis bongkahan sekaligus melalui fungsi-fungsi seperti baca () dan menulis().

  1. Apa artinya memindahkan file semacam itu di sekitar sistem file (yaitu, memindahkan file tersebut dari direktori ke direktori lain)? Apa yang saya pahami adalah, karena file tersebut dipetakan memori, proses (es) berinteraksi dengan file selalu menulis ke wilayah yang telah ditentukan dari memori utama, dan ketika kita membuka file itu (misalnya menggunakan vim), kita membaca wilayah itu dari memori utama (jadi, tidak ada disk yang terlibat). Karenanya, di mana pun kita memindahkan file, itu akan selalu berfungsi dengan benar, bukan? Jika ya, apakah memindahkan file di sekitar sistem file memiliki arti penting?

Jika Anda memindahkannya dalam sistem file yang sama, Anda benar-benar hanya bergerak di sekitar referensi, sebuah inode dari satu direktori ke direktori lain. Jika ada program yang sudah membuka file ini, mereka masih akan mengakses file yang sama karena mereka sudah memiliki inode di tangan melalui deskriptor file. Inilah yang terjadi dengan file table_name.idb yang Anda sebutkan dalam komentar.

  1. Apakah ada perintah yang akan memberi tahu jika file dipetakan memori?

Wossname sudah menjawab ini untuk file yang dipetakan memori. lsofakan memberi tahu Anda proses mana yang dipetakan memori file.

Untuk mengetahui apakah suatu file berada dalam sistem file yang berada di memori, Anda dapat menggunakan dfatau mountuntuk membuat daftar sistem file dan titik mountnya. Anda hanya perlu tahu jenis sistem file mana yang berada di memori dengan mencarinya (misalnya di wikipedia).

  1. Akhirnya, jika saya membuka file yang dipetakan dengan vim, buat beberapa perubahan dan simpan serta tutup vim, apa yang akan terjadi? Apakah perubahan saya hanya akan ditulis ke memori utama? Jika demikian, apakah proses lain yang menggunakan file ini akan melihat perubahan yang baru saja saya buat? Dalam pengalaman saya, proses lain tidak melihat perubahan yang saya buat pada file ketika saya membuat beberapa perubahan pada file dengan vim. Apa alasannya?

Secara pribadi, saya belum menggunakan mmapfungsi dalam program C, tapi seperti yang saya pahami dari membaca sekilas man mmapdan info mmap, tidak ada keajaiban yang terlibat dalam mempertahankan representasi dalam memori dalam sinkronisasi. Dalam bentuk dasarnya, memanggil mmap menyalin isi file ke memori dan msyncdigunakan untuk menulisnya kembali dari memori ke disk. Jika file pada disk berubah, tidak ada yang tersedia untuk mendeteksi itu dan secara otomatis mengubah representasi dalam memori dalam semua proses yang memetakannya.

EDIT: Ternyata mmap () benar-benar mencoba untuk menjaga representasi dalam memori tetap sinkron dalam beberapa kondisi. Jika peta hanya dibaca dari, peta itu akan tetap disinkronkan bahkan ketika proses lain menulis ke file. Jika ditulis ke (dengan menetapkan ke wilayah memori), apa yang terjadi tergantung pada bendera MAP_SHARED atau MAP_PRIVATE yang tampaknya wajib diberikan ke mmap (). Jika MAP_PRIVATE disediakan, peta bercabang dari representasi di-disk dan berhenti disinkronkan hingga Anda menggunakan msync (). Jika MAP_SHARED disediakan, maka pembaruan dibuat terlihat oleh proses lain yang memiliki file dipetakan, serta (meskipun ini tidak langsung diperlukan) representasi pada disk.

Saya baru saja membuka vim pada file yang ada e, dan menjalankan perintah :w, sambil inotifywait -m .menjalankan di terminal lain. Di antara beberapa bagian aneh, ini adalah bagian penting yang saya dapatkan inotifywait.

./ MOVED_FROM e
./ MOVED_TO e~
./ CREATE e
./ OPEN e
./ MODIFY e
./ CLOSE_WRITE,CLOSE e
./ ATTRIB e
./ ATTRIB e
./ DELETE e~

Vim membuat file baru, dan menghapus yang lama. Mengapa ini dilakukan alih-alih memodifikasi file berada di luar cakupan pertanyaan ini, tetapi intinya adalah bahwa ini adalah file baru dan karenanya memiliki inode baru.

Sekarang, apa yang Anda maksud dengan proses lain menggunakan file ini? Jika yang Anda maksud adalah proses yang memiliki file dibuka saat Anda melakukan ini, tidak mereka tidak akan melihat perubahan. Ini karena, meskipun mereka membuka file dengan jalur yang sama, mereka bukan file yang sama. Jika Anda maksud proses yang dapat membuka file setelah Anda melakukan ini, maka ya mereka akan melihat perubahannya. Mereka akan membuka file baru yang Anda buat.

Penting untuk dicatat bahwa meskipun program tampaknya memiliki file terbuka di antarmuka pengguna, itu tidak berarti bahwa mereka menjaga file tetap terbuka dalam proses. Vim adalah contohnya, seperti yang ditunjukkan di atas.

JoL
sumber
3
" Jika file pada disk berubah, tidak ada yang ada untuk mendeteksi itu dan secara otomatis mengubah representasi dalam memori dalam semua proses yang memetakannya. " Apa yang akan mengubah sistem file pada disk di belakang pemetaan halaman OS? sistem? Apakah Anda membayangkan beberapa akses mentah ke perangkat blok atau perangkat blok yang dibagikan melalui iSCSI atau sesuatu?
David Schwartz
@ david-schwartz Tidak. Saya membayangkan dua proses memiliki file yang terbuka () ed. Proses 1 menggunakan mmap () untuk membuat konten file disalin / dipetakan ke memori. Kemudian, proses 2 menggunakan write () (dan mungkin fsync ()) untuk mengubah konten pada disk. Pada saat ini, proses isi file 1 dalam memori tidak mencerminkan proses perubahan 2 lakukan, kan?
JoL
Tidak, tentu saja tidak. Tujuan dari writefungsi ini adalah untuk mengubah data file. Itu mungkin atau mungkin tidak berarti mengubah isi pada disk, tetapi apa pun yang terlibat, itu adalah tanggung jawab sistem file untuk memperbaikinya. Dalam hal ini, itu akan melibatkan memodifikasi halaman memori yang dipetakan dan menandainya kotor.
David Schwartz
@ david-schwartz Saya bereksperimen dengan mmap (), dan Anda agak benar. Dalam skenario yang saya paparkan dalam komentar saya sebelumnya, proses konten yang saya miliki dalam memori (dalam peta) sebenarnya mencerminkan perubahan kecuali proses 1 telah menulis ke memori dalam pemetaan sebelumnya. Ini benar bahkan ketika proses perubahan yang saya lakukan adalah di lokasi yang berbeda dari perubahan yang dilakukan oleh proses 2. Saya memperbarui jawaban dengan mencoret apa yang salah dan menambahkan apa yang saya temukan.
JoL
1
@ david-schwartz Maaf, saya tidak bermaksud mengatakan bahwa mmap berperilaku berbeda dari apa yang ditentukan oleh dokumentasi, tapi ya saya pikir saya telah membuat jawabannya terlalu membingungkan. Saya pikir ini masih dalam cakupan, tetapi pertanyaannya, "apakah proses lain yang menggunakan file ini akan melihat perubahan yang baru saja saya buat?", Tampaknya terlalu luas. Ada terlalu banyak "itu tergantung". Karena kebutuhan OP tampaknya murni otodidak, saya mencoba memberikan jawaban yang akurat dan mencakup sebanyak mungkin yang saya bisa, tetapi saya mungkin telah berlebihan. Padahal, saya masih senang saya lakukan, karena saya belajar sedikit juga.
JoL