cdadalah built-in shell yang diamanatkan POSIX :
Jika perintah sederhana menghasilkan nama perintah dan daftar argumen opsional, tindakan berikut harus dilakukan:
- Jika nama perintah tidak mengandung garis miring, langkah pertama yang berhasil dalam urutan berikut akan terjadi:
...
- Jika nama perintah cocok dengan nama utilitas yang tercantum dalam tabel berikut, utilitas itu harus dipanggil.
...
cd
...
- Kalau tidak, perintah harus dicari untuk menggunakan PATH ...
Meskipun ini tidak secara eksplisit mengatakan itu harus built-in, spesifikasi selanjutnya mengatakan, dalam deskripsicd :
Karena cd mempengaruhi lingkungan eksekusi shell saat ini, ia selalu disediakan sebagai built-in shell biasa.
Dari bashmanual :
Perintah built-in shell berikut ini diwarisi dari Bourne Shell. Perintah-perintah ini diimplementasikan sebagaimana ditentukan oleh standar POSIX.
...
cd
cd [-L|[-P [-e]]] [directory]
Saya kira Anda bisa memikirkan arsitektur di mana cdtidak harus menjadi builtin. Namun, Anda harus melihat apa yang tersirat built-in. Jika Anda menulis kode khusus di shell untuk melakukan sesuatu untuk beberapa perintah, Anda sudah hampir memiliki builtin. Semakin banyak yang Anda lakukan, semakin baik hanya memiliki builtin.
Sebagai contoh, Anda dapat meminta shell memiliki IPC untuk berkomunikasi dengan subproses, dan akan ada cdprogram yang akan memeriksa keberadaan direktori dan apakah Anda memiliki izin untuk mengaksesnya dan kemudian berkomunikasi dengan shell untuk memerintahkannya mengubah direktori. Namun, Anda harus kemudian memeriksa apakah proses berkomunikasi dengan Anda adalah anak-anak (atau membuat alat komunikasi khusus hanya dengan anak-anak, seperti deskriptor file khusus, memori bersama, dll.), Dan jika prosesnya memang benar menjalankan cdprogram tepercaya atau yang lainnya. Itu adalah sekaleng cacing.
Atau Anda bisa memiliki cdprogram yang membuat chdirsystem call, dan memulai shell baru dengan semua variabel lingkungan saat ini diterapkan ke shell baru, dan kemudian membunuh shell induknya (entah bagaimana) ketika dilakukan. 1
Lebih buruk lagi, Anda bahkan dapat memiliki sistem di mana suatu proses dapat mengubah lingkungan proses lain (saya pikir secara teknis Anda dapat melakukan ini dengan para penentang). Namun sistem seperti itu akan sangat, sangat rentan.
Anda akan menemukan diri Anda menambahkan kode lebih banyak dan lebih banyak untuk mengamankan metode seperti itu, dan itu jauh lebih mudah untuk membuatnya menjadi builtin.
Bahwa sesuatu itu executable tidak mencegahnya menjadi builtin. Inti masalah:
echo dan test
echodan testmerupakan utilitas yang diamanatkan POSIX ( /bin/echodan /bin/test). Namun hampir setiap shell populer memiliki builtin echodan test. Demikian pula, killbuiltin yang tersedia sebagai program. Lainnya termasuk:
sleep (tidak seperti biasa)
time
false
true
printf
Namun, ada beberapa kasus di mana perintah tidak bisa apa-apa selain builtin. Salah satunya adalah cd. Biasanya, jika path lengkap tidak ditentukan, dan nama perintah cocok dengan yang builtin, fungsi yang cocok dengan perintah itu disebut. Bergantung pada shell, perilaku bawaan dan perilaku yang dapat dieksekusi mungkin berbeda (ini khususnya masalahecho , yang memiliki perilaku yang sangat berbeda . Jika Anda ingin memastikan perilaku tersebut, lebih baik untuk memanggil yang dapat dieksekusi menggunakan path lengkap, dan mengatur variabel seperti POSIXLY_CORRECT(bahkan saat itu tidak ada jaminan nyata).
Secara teknis tidak ada yang mencegah Anda menyediakan OS yang juga sebuah shell dan memiliki setiap perintah sebagai builtin. Dekat dengan ujung ekstrem ini adalah BusyBox monolitik . BusyBox adalah biner tunggal, yang (tergantung pada namanya) dapat berperilaku sebagai salah satu dari lebih dari 240 program , termasuk Shell Almquist ( ash). Jika Anda membatalkan PATHpengaturan saat menjalankan BusyBox ash, program yang tersedia di BusyBox masih dapat diakses oleh Anda tanpa menentukan a PATH. Mereka hampir menjadi builtin shell, kecuali bahwa shell itu sendiri adalah semacam builtin ke BusyBox.
Jika Anda melihat dashsumbernya, utas eksekusi adalah sesuatu seperti ini (tentu saja, dengan fungsi tambahan yang terlibat ketika pipa dan hal-hal lain digunakan):
main→ cmdloop→ evaltree→evalcommand
evalcommandlalu gunakan findcommanduntuk menentukan apa perintahnya. Jika itu adalah builtin, maka :
case CMDBUILTIN:
if (spclbltin > 0 || argc == 0) {
poplocalvars(1);
if (execcmd && argc > 1)
listsetvar(varlist.list, VEXPORT);
}
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
if (exception == EXERROR && spclbltin <= 0) {
FORCEINTON;
break;
cmdentry.u.cmdadalah struct( struct builtincmd), yang salah satu anggotanya adalah pointer fungsi, dengan tanda tangan khas main: (int, char **). The evalbltinfungsi panggilan (tergantung pada apakah builtin adalah evalperintah atau tidak) baik evalcmd, atau fungsi pointer ini. Fungsi sebenarnya didefinisikan dalam berbagai file sumber. echo, misalnya, adalah :
int
echocmd(int argc, char **argv)
{
int nonl;
nonl = *++argv ? equal(*argv, "-n") : 0;
argv += nonl;
do {
int c;
if (likely(*argv))
nonl += print_escape_str("%s", NULL, NULL, *argv++);
if (nonl > 0)
break;
c = *argv ? ' ' : '\n';
out1c(c);
} while (*argv);
return 0;
}
Semua tautan ke kode sumber di bagian ini berbasis nomor baris, sehingga dapat berubah tanpa pemberitahuan.
1 sistem POSIX memang cddapat dieksekusi .
Catatan:
Ada banyak posting bagus di Unix & Linux yang berhubungan dengan perilaku shell. Khususnya:
Jika Anda belum melihat pola dalam pertanyaan yang terdaftar sejauh ini, hampir semuanya melibatkan Stéphane Chazelas .
typeperintah