cda, 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 bashmanuel :
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 cdyerleş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 cdve 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 cdprogramı veya başka bir şeyi çalıştırmak. Bu bir sürü solucan.
Veya sistem çağrısı cdyapan bir programınız olabilir chdirve 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
echove testPOSIX zorunlu görev programlarıdır ( /bin/echove /bin/test). Oysa hemen hemen her popüler kabuğun bir yapısı vardır echove test. Benzer şekilde, killbir 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.
dashKaynağ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
evalcommandsonra findcommandkomutun 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.cmdbir struct( struct builtincmd), üyeleri bir işlev gösterici, tipik bir imza ile bir main: (int, char **). evalbltinFonksiyon aramalar (yerleşik olup olmadığına bağlı olarak evalya 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 .
typekomutun kullanılması önerilir