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?
Jawaban:
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) .
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
,htop
ataucat /proc/self/maps
ataucat /proc/$$/maps
(lihat proc (5) ).PS. Saya fokus pada Linux, tetapi OS lain juga memiliki memori virtual dan cache halaman.
sumber
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
awk
itu 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
Karena shell harus memperluas
$(cat file)
substitusi perintah sepenuhnya sebelum menjalankan bahkan iterasi pertamafor
loop, ini akan membaca keseluruhan darifile
ke dalam memori (ke dalam memori yang digunakan oleh shell yang mengeksekusifor
loop). Ini agak konyol dan juga tidak bagus. Sebaliknya, yang harus dilakukanIni akan memproses
file
baris 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
awk
program 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 melaluizcat
ataugzip -d -c
, yang, sejakgzip
melakukan 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.
sumber
awk
,{ a[i++] = $0 }
akan menambahkan semua baris file input ke arraya
. Anda mungkin juga ingin mencari fungsi Cmmap()
, tetapi penggunaannya mungkin agak di luar topik di sini.sed
,,awk
dan 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.sed
hanya 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 menjalankansed
file 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_cacheTidak. 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).
sumber