cd
a, POSIX zorunlu kabuk yerleşik:
Basit bir komut, bir komut ismiyle ve isteğe bağlı bir argüman listesiyle sonuçlanırsa, aşağıdaki eylemler gerçekleştirilir:
- Komut adı eğik çizgi içermiyorsa, aşağıdaki sıradaki ilk başarılı adım gerçekleşir:
...
- Komut adı, aşağıdaki tabloda listelenen bir yardımcı programın adıyla eşleşiyorsa, bu yardımcı program çağrılmalıdır.
...
cd
...
- Aksi takdirde, komut PATH kullanımı için aranır ...
Bu açıkça bir yerleşik olması gerektiğini söylese de , tarifnamede şöyle açıklanmaktadırcd
:
Cd mevcut kabuk yürütme ortamını etkilediğinden, her zaman düzenli yerleşik bir kabuk olarak sağlanır.
Gönderen bash
manuel :
Aşağıdaki kabuk yerleşik komutları Bourne Kabuğundan miras alınır. Bu komutlar POSIX standardında belirtildiği şekilde uygulanır.
...
cd
cd [-L|[-P [-e]]] [directory]
Sanırım cd
yerleşik olması gerekmeyen bir mimariyi düşünebilirsin . Ancak, bir yerleşikin ne anlama geldiğini görmek zorundasınız. Bazı komutlar için bir şeyler yapmak üzere kabuğa özel bir kod yazarsanız, bir yerleşik yapıya yakınlaşırsınız. Ne kadar çok yaparsanız, basitçe bir yerleşime sahip olmak o kadar iyidir.
Örneğin, alt işlemlerle iletişim kurmak için kabuğun IPC'sine sahip olabilirsiniz cd
ve dizinin varlığını ve erişim izninizin olup olmadığını kontrol etmenizi sağlayan bir program olur ve ona kabukla iletişim kurmasını söyler. dizin. Bununla birlikte, sizinle iletişim kuran sürecin bir çocuk olup olmadığını (veya özel bir dosya tanıtıcısı, paylaşılan hafıza vb. Gibi yalnızca çocuklarla özel iletişim araçları kullanın) ve işlemin gerçek olup olmadığını kontrol etmeniz gerekir. güvenilir cd
programı veya başka bir şeyi çalıştırmak. Bu bir sürü solucan.
Veya sistem çağrısı cd
yapan bir programınız olabilir chdir
ve yeni kabuğa uygulanan tüm geçerli ortam değişkenleriyle yeni bir kabuk başlatır ve ardından bittiğinde üst kabuğunu (bir şekilde) öldürür. 1
Daha da kötüsü, bir işlemin diğer işlem ortamlarını değiştirebileceği bir sisteme bile sahip olabilirsiniz (teknik olarak hata ayıklayıcılarla yapabileceğinizi düşünüyorum). Bununla birlikte, böyle bir sistem çok ama çok savunmasız olacaktır.
Kendinizi bu tür metotları güvence altına almak için giderek daha fazla kod ekleyeceksiniz ve basitçe bir yerleşik yapmak oldukça daha kolaydır.
Bir şeyin çalıştırılabilir olması, yerleşik olmasını engellemez. Konuşma konusu olan mesele:
echo
ve test
echo
ve test
POSIX zorunlu görev programlarıdır ( /bin/echo
ve /bin/test
). Oysa hemen hemen her popüler kabuğun bir yapısı vardır echo
ve test
. Benzer şekilde, kill
bir program olarak mevcut yerleşiktir. Diğerleri şunlardır:
sleep
(yaygın değil)
time
false
true
printf
Bununla birlikte, bir komutun yerleşik olmayan bir şey olamayacağı bazı durumlar vardır. Bunlardan biri cd
. Genellikle, tam yol belirtilmezse ve komut adı bir yerleşikin adıyla eşleşiyorsa, o komuta uygun bir işlev çağrılır. Kabuğa bağlı olarak, yapının ve çalıştırılabilir dosyanın davranışı farklı olabilir (bu özellikle çılgınca farklı davranışlara sahip olan bir sorundurecho
. tam yol ve gibi değişkenler ayarlayın (o zaman bile gerçek bir garanti yoktur).POSIXLY_CORRECT
Teknik olarak, aynı zamanda bir kabuk olan ve yerleşik olarak her komutu olan bir işletim sistemi sağlamanızı önleyen hiçbir şey yoktur. Bu aşırı uç yakın, monolitik BusyBox . BusyBox, (adı verilen isme bağlı olarak) bir Almquist Shell ( ) dahil olmak üzere 240 programdan herhangi biri gibi davranabileceği tek bir ikilidir ash
. BusyBox'ı PATH
çalıştırırken ayırırsanız ash
, BusyBox'ta bulunan programlara a belirtmeden erişebilirsiniz PATH
. Onlar kabuk yerleşiklerine yaklaşıyorlar, ancak kabuğun kendisi BusyBox'a özgü bir yerleşik.
dash
Kaynağa bakarsanız , yürütme ipliği şunun gibi bir şeydir (elbette, borular ve diğer şeyler kullanıldığında ilave işlevlerle birlikte):
main
→ cmdloop
→ evaltree
→evalcommand
evalcommand
sonra findcommand
komutun ne olduğunu belirlemek için kullanır . Bir yerleşik ise, o zaman :
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.cmd
bir struct
( struct builtincmd
), üyeleri bir işlev gösterici, tipik bir imza ile bir main
: (int, char **)
. evalbltin
Fonksiyon aramalar (yerleşik olup olmadığına bağlı olarak eval
ya komut ya da değil) evalcmd
, veya bu fonksiyon işaretçi. Gerçek fonksiyonlar çeşitli kaynak dosyalarında tanımlanmıştır. echo
, örneğin :
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;
}
Bu bölümdeki kaynak koduna olan tüm bağlantılar satır numarası bazındadır, bu nedenle önceden haber verilmeksizin değiştirilebilir.
1 POSIX sistemlerinde cd
çalıştırılabilir bir dosya var .
Kenar notu:
Unix ve Linux'ta kabuk davranışı ile ilgilenen birçok mükemmel yazı var. Özellikle:
Şimdiye kadar listelenen sorularda bir model farketmediyseniz, neredeyse hepsi Stéphane Chazelas'ı içerir .
type
komutun kullanılması önerilir