Kapan perintah bawaan dimuat ke memori

11

Katakanlah jika saya mengetikkan cdshell saya. Apakah cddimuat dari memori pada saat itu? Intuisi saya adalah bahwa perintah bawaan ini sudah dimuat sebelumnya ke memori sistem setelah kernel dimuat, tetapi seseorang bersikeras bahwa itu hanya dimuat ketika saya benar-benar menjalankan perintah (tekan enter pada shell). Bisakah Anda memberi tahu saya jika ada referensi yang menjelaskan hal ini?

Forethinker
sumber
1
Saya pikir jawaban ini akan membantu Anda memahami, meskipun itu bukan duplikat.
cjm
@ cjm: Terima kasih itu memang penjelasan yang bagus untuk dibaca.
Forethinker

Jawaban:

9

Katakanlah jika saya mengetikkan cd di shell saya. Apakah cd dimuat dari memori pada saat itu? Intuisi saya adalah bahwa perintah bawaan ini sudah dimuat sebelumnya ke memori sistem setelah kernel dimuat, tetapi seseorang bersikeras bahwa perintah itu dimuat hanya ketika saya benar-benar menjalankan perintah ...

Secara umum jawaban lain benar - built-in dimuat dengan shell, stand -one dimuat ketika dipanggil. Namun, "seseorang" musang yang sangat kuat bisa bersikeras bahwa itu tidak sesederhana itu.

Diskusi ini agak tentang bagaimana OS bekerja, dan OS yang berbeda bekerja dengan cara yang berbeda, tetapi saya pikir secara umum berikut ini mungkin benar untuk semua nix * kontemporer.

Pertama, "dimuat ke dalam memori" adalah frasa yang ambigu; benar-benar apa yang kita maksudkan adalah ruang alamat virtualnya dipetakan ke dalam memori . Ini penting karena "ruang alamat virtual" mengacu pada hal-hal yang mungkin perlu dimasukkan ke dalam memori, tetapi pada kenyataannya tidak pada awalnya: sebagian besar yang sebenarnya dimuat ke dalam memori adalah peta itu sendiri - dan peta itu bukan wilayah. "Wilayah" akan menjadi executable pada disk (atau dalam cache disk) dan, pada kenyataannya, sebagian besar dari itu mungkin tidak dimuat ke dalam memori ketika Anda menjalankan executable.

Juga, sebagian besar "wilayah" adalah referensi ke wilayah lain (perpustakaan bersama), dan sekali lagi, hanya karena mereka telah dirujuk tidak berarti mereka benar-benar dimuat juga. Mereka tidak dimuat sebelum mereka benar-benar digunakan, dan kemudian hanya potongan-potongan dari mereka yang benar-benar perlu dimuat agar "penggunaan" apa pun berhasil.

Sebagai contoh, berikut adalah potongan topoutput di linux yang merujuk pada sebuah bashinstance:

VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                  
113m 3672 1796 S  0.0  0.1   0:00.07 bash   

VIRT 113 MB adalah ruang alamat virtual, yang dipetakan dalam RAM. Tetapi RES adalah jumlah aktual RAM yang dikonsumsi oleh proses - hanya 3,7 kB. Dan dari itu, beberapa adalah bagian dari wilayah bersama yang disebutkan di atas - 1,8 kB SHR. Tapi /bin/bashdisk saya di 930 kB, dan libc dasar itu terhubung ke (lib bersama) dua kali lebih besar lagi.

Shell itu tidak melakukan apa-apa sekarang. Katakanlah saya menjalankan perintah bawaan, yang kami katakan sebelumnya sudah "dimuat ke dalam memori" bersama dengan sisa dari shell. Kernel mengeksekusi kode apa pun yang terlibat mulai dari suatu titik di peta, dan ketika mencapai referensi ke kode yang belum benar-benar dimuat, kernel memuatnya - dari gambar yang dapat dieksekusi pada disk - meskipun secara lebih kasual akal, bahwa executable (baik itu shell, alat yang berdiri sendiri, atau perpustakaan bersama) sudah "dimuat ke dalam memori".

Ini disebut paging permintaan .

goldilocks
sumber
9

Sambil menunggu salah satu kelas berat datang dan memberikan perspektif sejarah penuh, saya akan memberi Anda pemahaman saya yang lebih terbatas.

Built-in perintah seperti alias, cd, echodll adalah bagian dari shell Anda ( bash, zsh, kshatau apa pun). Mereka dimuat pada saat yang sama shell dan hanya fungsi internal shell itu.

terdon
sumber
4

Saya melakukan percobaan berikut untuk menunjukkan bahwa perintah builtin sebenarnya dimuat sebagai bagian dari exectuable bash. Karena itulah mengapa mereka disebut builtin, tetapi demo selalu merupakan cara terbaik untuk membuktikan sesuatu.

Contoh

  1. Mulai bashshell baru , dan catat ID prosesnya (PID):

    $ bash
    $ echo $$
    6402
    
  2. Di terminal kedua jalankan psperintah sehingga kita dapat menonton dan melihat apakah bashmulai mengambil memori tambahan:

    $ watch "ps -Fp 6402"
    

    Outputnya terlihat seperti ini:

    Every 2.0s: ps -Fp 6402                        Sat Sep 14 14:40:49 2013
    
    UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
    saml      6402  6349  0 28747  6380   1 14:33 pts/38   00:00:00 bash
    

    CATATAN: Penggunaan memori ditunjukkan dengan kolom SZ & RSS di sini.

  3. Mulai menjalankan perintah di shell (pid 6402):

    Ketika Anda di cdsekitar Anda akan melihat memori sebenarnya naik, tetapi ini bukan karena dieksekusi cddimuat ke dalam memori, melainkan ini karena struktur direktori pada disk semakin dimuat ke dalam memori. Jika Anda terus cdke direktori lain Anda akan melihatnya secara bertahap terus naik.

    Every 2.0s: ps -Fp 30208                        Sat Sep 14 15:11:22 2013
    
    UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
    saml     30208  6349  0 28780  6492   0 15:09 pts/38   00:00:00 bash
    

    Anda dapat melakukan lebih banyak tes rumit seperti ini:

    $ for i in `seq 1000`; do cd ..; cd 90609;done
    

    Perintah ini akan naik satu tingkat dan kemudian kembali ke direktori 90609 1000 kali. Saat menjalankan ini jika Anda memantau penggunaan memori di psjendela Anda akan melihat bahwa itu tidak berubah. Saat menjalankan sesuatu seperti ini, tidak ada penggunaan memori tambahan yang harus diperhatikan.

  4. strace

    Berikut ini adalah contoh lain bahwa kita sedang berurusan dengan fungsi builtin bashdaripada eksekusi yang sebenarnya. Ketika Anda mencoba dan menjalankan strace cd ..Anda akan mendapatkan pesan berikut:

    $ strace cd ..
    strace: cd: command not found
    
slm
sumber
3

"perintah bawaan" mengacu pada perintah yang ada di dalam shell, bukan sebagai program yang terpisah. ls, misalnya, sebenarnya bukan perintah bawaan tetapi program terpisah. Ini akan dimuat ke dalam RAM ketika dipanggil, kecuali sudah ada di cache disk.

Contoh dari perintah bawaan adalah printfatau cd. Ini adalah bagian dari shell, dan dimuat bersama dengan sisa shell.

Tidak ada perintah yang dimuat sebelumnya secara default, meskipun sistem telah dibuat untuk melakukan ini.

wingedsubmariner
sumber