Mengapa ls
membutuhkan proses terpisah untuk pelaksanaannya? Saya tahu alasan mengapa perintah suka cd
tidak bisa dijalankan dengan mekanisme forking tetapi apakah ada salahnya jika ls
dieksekusi tanpa forking?
Mengapa ls
membutuhkan proses terpisah untuk pelaksanaannya? Saya tahu alasan mengapa perintah suka cd
tidak bisa dijalankan dengan mekanisme forking tetapi apakah ada salahnya jika ls
dieksekusi tanpa forking?
Jawaban:
Jawabannya kurang lebih itu ls
adalah eksekusi eksternal. Anda dapat melihat lokasinya dengan menjalankan type -p ls
.
Mengapa tidak ls
dibangun ke dalam shell? Nah, mengapa harus begitu? Tugas shell bukanlah untuk mencakup setiap perintah yang tersedia, tetapi untuk menyediakan lingkungan yang mampu menjalankannya. Beberapa shell modern memiliki echo
, printf
dan sejenisnya sebagai builtin, yang secara teknis tidak harus builtin, tetapi dibuat untuk alasan kinerja ketika dijalankan berulang kali (terutama dalam loop ketat). Tanpa membuat mereka builtin, shell harus memotong dan mengeksekusi proses baru untuk setiap panggilan kepada mereka, yang bisa sangat lambat.
Paling tidak, menjalankan ls
, executable eksternal, membutuhkan menjalankan salah satu keluarga panggilan sistem exec. Anda bisa melakukan ini tanpa forking, tetapi itu akan menggantikan shell utama yang Anda gunakan. Anda dapat melihat apa yang terjadi dalam contoh itu dengan melakukan hal berikut:
exec ls; echo "this never gets printed"
Karena gambar proses shell Anda diganti, shell saat ini tidak lagi dapat diakses setelah melakukan ini. Agar shell dapat terus berjalan setelah menjalankan ls, perintah tersebut harus dibangun ke dalam shell.
Forking memungkinkan penggantian proses yang bukan shell utama Anda, yang berarti Anda dapat terus menjalankan shell Anda sesudahnya.
echo
, printf
, dll
cd
tidak dapat dieksekusi eksternal?
cd
dieksekusi dalam sistem operasi POSIX-compliant ( lihat di sini ). Jika Anda ingin benar-benar chdir () dalam proses saat ini, Anda harus memasukkannya ke dalam shell.
The Bash Reference Manual negara:
Perintah builtin diperlukan untuk mengimplementasikan fungsionalitas yang tidak mungkin atau tidak nyaman untuk didapatkan dengan utilitas terpisah.
Artinya, shell dirancang hanya untuk menyertakan perintah bawaan jika:
The ls
perintah tidak sesuai salah satu syarat-syarat di atas.
Namun , tidak ada kendala pemrograman yang akan mencegah ls
diimplementasikan sebagai built-in, yang mengeksekusi dalam proses yang sama dengan penerjemah bash. Alasan desain untuk perintah yang tidak diimplementasikan sebagai built-in shell adalah:
Mengenai alasan pertama - Anda ingin shell menjadi independen dan sekuat mungkin. Anda tidak ingin shell terjebak pada ls
mount NFS yang "tidak merespons masih mencoba".
Mengenai alasan kedua - Dalam banyak kasus Anda mungkin ingin menggunakan shell untuk sistem yang menggunakan Busybox atau sistem file lain yang memiliki ls
implementasi yang berbeda . Atau bahkan menggunakan sumber shell yang sama di OS yang memiliki ls
implementasi yang berbeda .
Mengenai alasan ketiga - Untuk ekspresi seperti find . -type d | xargs ls -lad
itu akan sulit atau tidak mungkin untuk menerapkan ls
dalam proses yang sama dengan shell interpreter.
Mengenai alasan keempat - Beberapa ls
perintah bisa memakan waktu lama untuk diselesaikan. Anda mungkin ingin shell terus melakukan sesuatu yang lain sementara itu.
Catatan: Lihat posting bermanfaat ini oleh Warren Young dalam menanggapi pertanyaan serupa.
ls
ke dalam proses eksternal. Itu bisa dilakukan, tetapi itu akan rumit.
bash
keluaran alias | grep ls
. masukancat /etc/passwd | while read a; do echo "$a"; done
ls
tidak memerlukan proses terpisah. Sangat sedikit perintah yang benar-benar memerlukan proses terpisah: hanya yang perlu mengubah hak istimewa.
Sebagai aturan, shell mengimplementasikan perintah sebagai builtin hanya ketika perintah itu perlu diimplementasikan sebagai builtin. Perintah seperti alias
, cd
, exit
, export
,jobs
, ... perlu untuk membaca atau memodifikasi beberapa keadaan internal dari shell, dan karena itu tidak dapat menjadi program terpisah. Perintah yang tidak memiliki persyaratan seperti itu dapat berupa perintah terpisah; dengan cara ini, mereka dapat dipanggil dari shell atau program lain.
Melihat daftar builtin di bash, hanya builtin berikut yang dapat diimplementasikan sebagai perintah terpisah. Bagi beberapa dari mereka, akan ada sedikit kehilangan fungsi.
command
- tetapi itu akan kehilangan kegunaannya dalam situasi di mana PATH
mungkin tidak diatur dengan benar dan script menggunakan command
sebagai bagian dari pengaturannya.echo
- Ini adalah builtin untuk efisiensi.help
- bisa menggunakan database terpisah, tetapi menanamkan teks bantuan di shell executable memiliki keuntungan membuat shell executable mandiri.kill
- ada dua keuntungan dalam memiliki builtin: ia dapat mengenali penunjukan pekerjaan selain ID proses, dan dapat digunakan bahkan ketika tidak ada sumber daya yang cukup untuk memulai proses terpisah.printf
- Untuk alasan yang sama seperti echo
, dan juga untuk mendukung -v
opsi untuk menempatkan output dalam variabel.pwd
- builtin menawarkan kemampuan tambahan untuk pelacakan direktori saat ini yang logis (membiarkan tautan simbolik tetap utuh alih-alih meluaskannya).test
- itu adalah builtin untuk efisiensi (dan bash juga melakukan sihir dengan file yang dipanggil /dev/fd/…
pada beberapa sistem operasi)Beberapa cangkang menawarkan sejumlah besar builtin tambahan. Ada sash , yang merupakan shell yang dirancang untuk menjadi biner mandiri untuk perbaikan darurat (ketika beberapa perintah eksternal mungkin tidak dapat digunakan). Ini memiliki built-in ls
, disebut -ls
, serta alat-alat lain seperti -grep
dan -tar
. Sash's builtin memiliki kemampuan lebih sedikit daripada perintah penuh. Zsh menawarkan beberapa builtin serupa dalam modul zsh / file-nya . Tidak ada ls
, tetapi ekspansi wildcard ( echo *
) dan zstat
dapat melayani fungsi serupa.
Saya pikir ada sesuatu yang orang hilang di sini adalah kompleksitas geser dari ls
program GNU di Linux. Membandingkan ukuran executable ls
to bash
dan dash
shell pada sistem Debian saya, kami melihat bahwa itu cukup besar:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
Termasuk ls
fitur penuh sebagai versi GNU bash
akan meningkatkan ukuran yang dapat dieksekusi sebesar 10%. Ukurannya hampir sama dengan dash
cangkang penuh !
Sebagian besar shell builtin dipilih karena mereka berintegrasi dengan shell dengan cara yang tidak dapat dieksekusi oleh eksternal (pertanyaan menunjukkan cd
, tetapi contoh lain adalah versi bash untuk kill
mengintegrasikan dengan kontrol bash job) atau karena mereka adalah perintah yang sangat sederhana untuk diimplementasikan, memberikan hasil besar kecepatan vs ukuran ( true
danfalse
sesederhana yang didapat).
GNU ls
memiliki siklus pengembangan yang panjang dan mengimplementasikan opsi-opsi untuk menyesuaikan apa / bagaimana hasil ditampilkan. Menggunakan bawaan secara default akan kehilangan fungsionalitas ini atau secara signifikan meningkatkan kompleksitas dan ukuran shell.
Ini melakukan apa yang Anda cari:
printf "%s\n" *
Anda juga dapat menyimpan nama file dalam array:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Tapi itu tidak peduli tentang spasi dalam nama.
Ini berlaku untuk variabel dan peduli ruang:
printf "%s\n" * | while read a; do echo $a; done
ls
merupakan program eksternal,echo *
atauecho * .*
(tergantung pada opsi shell) melakukan pekerjaan yang cukup baik dari daftar file tanpa forking.