Yürütülmesi için neden ls
ayrı bir işlem gerekiyor? Gibi komutların cd
çatallama mekanizması ile yürütülememesinin nedenini biliyorum ama çatalsız yürütüldüğünde herhangi bir zarar var ls
mı?
Yürütülmesi için neden ls
ayrı bir işlem gerekiyor? Gibi komutların cd
çatallama mekanizması ile yürütülememesinin nedenini biliyorum ama çatalsız yürütüldüğünde herhangi bir zarar var ls
mı?
Yanıtlar:
Cevap az ls
çok harici bir yürütülebilir dosyadır. Konumunu çalıştırarak görebilirsiniz type -p ls
.
ls
Öyleyse neden kabuğun içinde değil ? Neden olsun ki? Bir kabuğun işi mevcut tüm komutları kapsamak değil, bunları çalıştırabilen bir ortam sağlamaktır. Bazı modern kabuklar var echo
, printf
ve yok builtins, bunların ilk teknik builtins olmak zorunda, ama onlar (öncelikle sıkı döngüler içinde) sürekli olarak çalıştırılır performans nedenleriyle bu yüzden yapılır. Onları yerleşik hale getirmeden, kabuk her bir çağrı için çatallanmalı ve yeni bir süreç yürütmelidir, bu da son derece yavaş olabilir.
En azından, çalıştırılabilir ls
, harici bir yürütülebilir dosya, sistem çağrılarının exec ailesinden birini çalıştırmayı gerektirir. Sen olabilir Çatallama olmadan bunu ancak kullandığınız birincil kabuğu yerini alacak. Aşağıdakileri yaparak o örnekte neler olduğunu görebilirsiniz:
exec ls; echo "this never gets printed"
Kabuğunuzun işlem görüntüsü değiştirildiği için, geçerli kabuğa bundan sonra erişilemez. Kabuğun ls çalıştırıldıktan sonra çalışmaya devam edebilmesi için, komut kabuğun içine yerleştirilmelidir.
Forking, birincil kabuğunuz olmayan bir işlemin değiştirilmesine izin verir, bu da daha sonra kabuğunuzu çalıştırmaya devam edebileceğiniz anlamına gelir.
echo
, printf
vb
cd
harici bir yürütülebilir dosya neden olmasın?
cd
POSIX uyumlu işletim sistemlerinde çalıştırılabilir ( burada bakınız ). Mevcut işlemde aslında chdir () yapmak istiyorsanız, kabuğun içine yerleştirilmiş olması gerekir.
Bash devletler:
Yerleşik komutlar, ayrı yardımcı programlarla elde edilmesi imkansız veya uygunsuz işlevsellik uygulamak için gereklidir.
Yani, mermiler yalnızca şu durumlarda yerleşik komutları içerecek şekilde tasarlanmıştır :
ls
Komut yukarıdaki requirments herhangi uymuyor.
Bununla birlikte , burada ls
yerleşik olarak uygulanmasını engelleyecek , bash yorumlayıcısıyla aynı işlemde çalışan hiçbir programlama kısıtlaması yoktur . Komutlar için tasarım nedenleri değil kabuk yerleşik ins olarak implmented ediliyor şunlardır:
İlk sebeple ilgili - Kabuğun mümkün olduğunca bağımsız ve dirençli olmasını istiyorsunuz. Kabuğun ls
"hala denemeye yanıt vermiyor" olan bir NFS yuvasına takılmasını istemezsiniz .
İkinci nedenle ilgili - Birçok durumda, Busybox veya farklı bir ls
uygulaması olan diğer dosya sistemi kullanan bir sistem için bir kabuk kullanmak isteyebilirsiniz . Ya da farklı ls
uygulamaları olan işletim sistemlerinde aynı kabuk kaynağını kullanın .
Üçüncü sebeple ilgili olarak - Kabuk yorumlayıcıyla aynı süreçte find . -type d | xargs ls -lad
uygulanması zor veya imkansız gibi bir ifade için ls
.
Dördüncü nedenle ilgili - Bazı ls
komutların tamamlanması uzun sürebilir. Bu arada kabuğun başka bir şey yapmaya devam etmesini isteyebilirsiniz.
Not: Bkz bu yararlı yazı ile Warren Young benzer bir soruya cevap olarak.
ls
harici bir sürece dönüştürmek zorundaysa, kabuğun kaynak kodunun ne kadar karmaşık olacağını düşünürdüm . Bu yapılabilirdi, ama karmaşık olurdu.
bash
çıktı alias | grep ls
. girişcat /etc/passwd | while read a; do echo "$a"; done
ls
ayrı bir işlem gerektirmez. Çok az komut aslında ayrı bir işlem gerektirir: sadece ayrıcalıkları değiştirmesi gerekenler.
Kural olarak, kabuklar yalnızca bu komutların yerleşik olarak uygulanması gerektiğinde komutları yerleşik olarak uygular. Komutları gibi alias
, cd
, exit
, export
, jobs
, ... bu nedenle okumak veya kabuğun bazı iç durumunu değiştirmek ve ihtiyacı ayrı programlar olamaz. Böyle bir gereksinimi olmayan komutlar ayrı komutlar olabilir; bu şekilde herhangi bir kabuktan veya başka bir programdan çağrılabilirler.
Bash içindeki yerleşikler listesine bakıldığında, yalnızca aşağıdaki yerleşikler ayrı komutlar olarak uygulanabilir. Bazıları için hafif bir işlevsellik kaybı olacaktır.
command
- ancak PATH
düzgün ayarlanamayacağı ve komut dosyasının command
kurulumun bir parçası olarak kullandığı durumlarda kullanışlılığını kaybeder .echo
- verimlilik için bir yerleşiktir.help
- ayrı bir veritabanı kullanabilir, ancak yardım metninin kabuk yürütülebilir dosyasına gömülmesi, kabuğun yürütülebilir dosyasını kendi içinde bulundurma avantajına sahiptir.kill
- yerleşik bir yapıya sahip olmanın iki avantajı vardır: işlem kimliklerine ek olarak iş tanımlarını tanıyabilir ve ayrı bir işlem başlatmak için yeterli kaynak olmasa bile kullanılabilir.printf
- aynı nedenden dolayı echo
ve aynı zamanda -v
çıktıyı bir değişkene koyma seçeneğini desteklemek .pwd
- yerleşik mantıksal geçerli dizin izleme ek yeteneği sunar (sembolik bağlantıları genişletmek yerine sağlam bırakır).test
- verimlilik için bir yerleşiktir (ve bash ayrıca /dev/fd/…
bazı işletim sistemlerinde çağrılan dosyalarla biraz sihir yapar ).Birkaç mermi önemli sayıda ek yerleşik yapı sunar. Acil onarımlar için bağımsız bir ikili olarak tasarlanmış bir kabuk olan kanat vardır (bazı harici komutlar kullanılamayabilirse). Yerleşik ls
, adı verilen ve ve -ls
gibi diğer araçlara sahiptir . Sash'in yerleşikleri tam teşekküllü komutlardan daha az kapasiteye sahiptir. Zsh, zsh / files modülünde benzer yapıları sunar . Sahip değil , joker karakter genişletmesi ( ) ve benzer bir işlevi yerine getirebilir.-grep
-tar
ls
echo *
zstat
İnsanların burada eksik olduğu bir şeyin ls
Linux'taki GNU programının kesme karmaşıklığı olduğunu düşünüyorum . Yürütülebilir boyutunu karşılaştırılması ls
için bash
ve dash
benim Debian sistemine kabukları, bunun oldukça büyük olduğunu görüyoruz:
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
ls
GNU sürümü kadar tam özellikli bir dahil edilmesi bash
, yürütülebilir boyutu% 10 artıracaktır. Neredeyse tam dash
kabuk ile aynı boyutta !
Çoğu kabuk yerleşkesi, kabukla harici yürütülebilir dosyaların yapamayacağı şekilde entegre oldukları için seçilir (soru işaret eder cd
, ancak başka bir örnek kill
bash iş kontrolüyle entegrasyonun bash sürümüdür ) veya uygulanması çok basit komutlar oldukları için, büyük bir hız vs boyut getirisi ( true
ve false
yaklaşık olarak basit).
GNU ls
uzun bir geliştirme döngüsüne sahiptir ve sonuçların hangi şekilde / nasıl görüntüleneceğini özelleştirme seçenekleri uygulayabilir. Varsayılan olarak yerleşik bir ls kullanmak bu işlevselliği kaybeder veya kabuk karmaşıklığını ve boyutunu önemli ölçüde artırır.
Aradığınızı yapın:
printf "%s\n" *
Ayrıca dosya adlarını dizide saklayabilirsiniz:
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
Ama isimlerdeki boşlukları umursamıyor
Bu değişkene geçer ve boşlukları umursar:
printf "%s\n" * | while read a; do echo $a; done
ls
Harici bir program olmasına rağmenecho *
veyaecho * .*
(kabuk seçeneklerine bağlı olarak) dosyaları çatallamadan listelemek için oldukça iyi bir iş çıkarır.