Apakah file dibuka oleh proses yang dimuat ke dalam RAM?

24

Perintah , misalnya sed, adalah program dan program dikodifikasi logika di dalam file dan file-file ini berada di suatu tempat di hard disk. Namun ketika perintah sedang dijalankan, salinan file mereka dari hard disk dimasukkan ke dalam RAM , di mana mereka menjadi hidup dan dapat melakukan hal-hal dan disebut proses .

Proses dapat menggunakan file lain, membaca atau menulis ke dalamnya, dan jika mereka melakukannya file tersebut disebut file terbuka. Ada perintah untuk menampilkan semua berkas terbuka dengan semua proses yang berjalan: lsof.

OK, jadi yang ingin saya tanyakan adalah apakah masa pakai perintah ganda, satu di hard disk, yang lain di RAM juga berlaku untuk file jenis lain, misalnya mereka yang tidak memiliki logika yang diprogram, tetapi hanya wadah untuk data.

Asumsi saya adalah, bahwa file yang dibuka oleh proses juga dimuat ke dalam RAM. Saya tidak tahu apakah itu benar, itu hanya sebuah intuisi.

Tolong, bisakah seseorang memahaminya?

sharkant
sumber

Jawaban:

27

Namun ketika perintah sedang dijalankan, salinan file-file mereka dari hard disk dimasukkan ke dalam RAM,

Ini salah (secara umum). Ketika sebuah program dieksekusi (melalui execve (2) ...) proses (menjalankan program itu) mengubah ruang alamat virtualnya dan kernel mengkonfigurasi ulang MMU untuk tujuan itu. Baca juga tentang memori virtual . Perhatikan bahwa program aplikasi dapat mengubah ruang alamat virtual menggunakan mmap (2) & munmap& mprotect (2) , juga digunakan oleh penghubung dinamis (lihat ld-linux (8) ). Lihat juga madvise (2) & posix_fadvise (2) & mlock (2) .

Masa Depan kesalahan halaman akan diproses oleh kernel ke beban (malas) halaman dari file executable. Baca juga tentang meronta - ronta .

Kernel menyimpan cache halaman yang besar . Baca juga tentang copy-on-write . Lihat juga readahead (2) .

OK, jadi yang ingin saya tanyakan adalah apakah masa pakai perintah ganda, satu di hard disk, yang lain di RAM juga berlaku untuk file jenis lain, misalnya mereka yang tidak memiliki logika yang diprogram, tetapi hanya wadah untuk data.

Untuk panggilan sistem seperti read (2) & write (2) cache halaman juga digunakan. Jika data yang akan dibaca ada di dalamnya, tidak ada IO disk yang akan dilakukan. Jika disk IO diperlukan, data yang sudah dibaca akan sangat mungkin dimasukkan ke dalam cache halaman. Jadi, dalam praktiknya, jika Anda menjalankan perintah yang sama dua kali, bisa terjadi bahwa tidak ada I / O fisik yang dilakukan pada disk untuk kedua kalinya (jika Anda memiliki hard disk yang berputar lama - bukan SSD - Anda mungkin mendengarnya; atau amati dengan cermat LED hard disk Anda).

Saya sarankan membaca buku seperti Sistem Operasi: Tiga Potongan Mudah (dapat diunduh secara bebas, satu file PDF per bab) yang menjelaskan semua ini.

Lihat juga Linux Makan saya RAM dan menjalankan perintah seperti xosview, top, htopatau cat /proc/self/mapsatau cat /proc/$$/maps(lihat proc (5) ).

PS. Saya fokus pada Linux, tetapi OS lain juga memiliki memori virtual dan cache halaman.

Basile Starynkevitch
sumber
35

Tidak, file tidak secara otomatis dibaca ke dalam memori dengan membukanya. Itu akan sangat tidak efisien. sed, misalnya, membaca inputnya baris demi baris, seperti halnya banyak alat Unix lainnya. Jarang harus menyimpan lebih dari garis saat ini dalam memori.

Dengan awkitu sama. Itu membaca catatan pada suatu waktu, yang secara default adalah garis. Jika Anda menyimpan bagian dari data input dalam variabel, itu akan menjadi ekstra, tentu saja 1 .

Beberapa orang memiliki kebiasaan melakukan hal-hal seperti

for line in $(cat file); do ...; done

Karena shell harus memperluas $(cat file)substitusi perintah sepenuhnya sebelum menjalankan bahkan iterasi pertama forloop, ini akan membaca keseluruhan dari fileke dalam memori (ke dalam memori yang digunakan oleh shell yang mengeksekusi forloop). Ini agak konyol dan juga tidak bagus. Sebaliknya, yang harus dilakukan

while IFS= read -r line; do ...; done <file

Ini akan memproses filebaris per baris (tetapi baca Memahami "IFS = baca -r baris" ).

Memproses file baris per baris dalam shell jarang diperlukan, karena sebagian besar utilitas berorientasi pada baris (lihat Mengapa menggunakan shell loop untuk memproses teks yang dianggap praktik buruk? ).

Saya bekerja di bioinformatika, dan ketika memproses sejumlah besar data genom, saya tidak akan bisa berbuat banyak kecuali saya hanya menyimpan bit data yang benar-benar diperlukan dalam memori. Sebagai contoh, ketika saya perlu menghapus bit data yang dapat digunakan untuk mengidentifikasi individu dari set data 1 terabyte yang berisi varian DNA dalam file VCF (karena tipe data itu tidak dapat dipublikasikan), saya melakukan baris per baris memproses dengan awkprogram sederhana (ini dimungkinkan karena format VCF berorientasi garis). Saya tidak membaca file ke dalam memori, memprosesnya di sana, dan menulisnya kembali! Jika file itu dikompresi, saya akan memberinya makan melalui zcatatau gzip -d -c, yang, sejak gzipmelakukan pemrosesan data, juga tidak akan membaca seluruh file ke dalam memori.

Bahkan dengan format file yang tidak berorientasi garis, seperti JSON atau XML, ada stream parser yang memungkinkan untuk memproses file besar tanpa menyimpan semuanya dalam RAM.

Dengan executable, ini sedikit lebih rumit karena perpustakaan bersama mungkin dimuat berdasarkan permintaan, dan / atau dibagi antara proses (lihat Memuat perpustakaan bersama dan penggunaan RAM , misalnya).

Caching adalah sesuatu yang belum saya sebutkan di sini. Ini adalah tindakan menggunakan RAM untuk menyimpan data yang sering diakses. File yang lebih kecil (misalnya file yang dapat dieksekusi) dapat di-cache oleh OS dengan harapan bahwa pengguna akan membuat banyak referensi. Terlepas dari pembacaan pertama file, akses selanjutnya akan dilakukan ke RAM daripada ke disk. Caching, seperti buffering input dan output biasanya sebagian besar transparan kepada pengguna dan jumlah memori yang digunakan untuk melakukan cache hal-hal dapat berubah secara dinamis tergantung pada jumlah RAM yang dialokasikan oleh aplikasi dll.


1 Secara teknis, sebagian besar program mungkin membaca sepotong input data sekaligus, baik menggunakan buffering eksplisit, atau secara implisit melalui buffering yang dilakukan perpustakaan I / O standar, dan kemudian menyajikan potongan itu baris demi baris ke kode pengguna. Jauh lebih efisien untuk membaca kelipatan ukuran blok disk daripada misalnya karakter pada satu waktu. Ukuran chunk ini jarang akan lebih besar dari beberapa kilobyte.

Kusalananda
sumber
Anda berkata, adalah mungkin untuk memuat pustaka bersama ke dalam RAM, apakah juga mungkin untuk memuat file biasa, yang hanya berisi data ke dalam RAM, bahkan jika itu tidak masuk akal?
sharkant
1
@sharkant Tentu saja. Itu hanya masalah menambahkan data ke variabel (atau array, atau hash, atau apa pun struktur data bahasa dalam persediaan yang dipersoalkan) sampai semua file telah disimpan. Dengan awk, { a[i++] = $0 }akan menambahkan semua baris file input ke array a. Anda mungkin juga ingin mencari fungsi C mmap(), tetapi penggunaannya mungkin agak di luar topik di sini.
Kusalananda
6
sed,, awkdan program berorientasi garis lainnya tidak membaca satu baris sekaligus ke dalam memori, karena file teks biasa tidak mengandung indeks garis, dan API sistem file dan perangkat keras penyimpanan tingkat rendah membaca satu atau lebih "sektor" (biasanya 512 atau 1024 byte) sekaligus. Saya akan terkejut jika kurang dari 8KB dibaca ke dalam memori oleh OS sebelum baris pertama diproses.
Russell Borogove
5
Meskipun utilitas seperti sedhanya akan membaca satu baris pada satu waktu ke dalam memori, perlu disebutkan bahwa sistem operasi akan menggunakan ram gratis untuk menyimpan file cache sehingga mereka dapat diakses dengan cepat. Jika Anda menjalankan sedfile yang lebih kecil, layak bahwa OS akan men-cache seluruh file dalam memori dan operasi akan dilakukan sepenuhnya dalam RAM. Lihat: en.wikipedia.org/wiki/Page_cache
Sean Dawson
5
@sharkant Ada gunanya memiliki file yang sepenuhnya dapat diakses di memori (lihat jawaban lain, mmap adalah panggilan sistem kata kunci di sini). Misalnya, sistem database biasanya ingin memiliki, untuk kemudahan dan kecepatan akses, seluruh database atau setidaknya beberapa indeks dipetakan ke dalam memori. Ini tidak selalu berarti bahwa semuanya sebenarnya ada dalam memori. OS bebas untuk "berpura-pura" bahwa file tersebut ada dalam memori. Ini memberitahu aplikasi "di sini, dalam rentang memori ini adalah file Anda", dan hanya sekali membaca dilakukan (seperti ketika proses telah ditukar), data sebenarnya dibaca.
Jonas Schäfer
5

Tidak. Walaupun memiliki pertunjukan RAM akhir-akhir ini sangat fantastis, ada saat ketika RAM adalah sumber daya yang sangat terbatas (saya belajar pemrograman pada VAX 11/750 dengan 2MB RAM) dan satu-satunya hal dalam RAM adalah executable aktif dan halaman data proses aktif, dan file data yang ada di cache buffer.
Cache buffer dihapus, dan halaman data ditukar. Dan sering kali. Halaman yang dapat dieksekusi read-only selesai ditulis dan tabel halaman ditandai jadi jika program menyentuh halaman-halaman itu lagi mereka di-paging dari filesystem. Data diolah dari dari swap. Seperti disebutkan di atas, perpustakaan STDIO menarik data dalam blok dan diperoleh oleh program sesuai kebutuhan: fgetc, fgets, fread, dll. Dengan mmap, file dapat dipetakan ke dalam ruang alamat suatu proses, seperti yang dilakukan dengan objek perpustakaan bersama atau bahkan file biasa. Ya, Anda mungkin memiliki beberapa tingkat kontrol jika dalam RAM atau tidak (mlock), tetapi hanya berjalan sejauh ini (lihat bagian kode kesalahan mlock).

Roger L.
sumber
1
Pernyataan "RAM Anda akan terlalu kecil untuk file Anda" benar sekarang seperti di masa lalu VAX.
Federico Poloni
1
@Federico_Poloni Tidak sepenuhnya benar hari ini. Di perusahaan terakhir saya, kami memiliki PC kelas workstation dengan 1TB RAM dan hanya 0,5Tb hard disk. (Kelas masalah: input kecil, output sedang, array besar yang diakses secara acak selama komputasi).
nigel222