Dlaczego „ls” wymaga osobnego procesu do wykonania?

14

Dlaczego lsjego wykonanie wymaga osobnego procesu? Znam powód, dla którego takich poleceń cdnie można wykonać za pomocą mechanizmu rozwidlenia, ale czy jest coś złego, jeśli lszostanie wykonane bez rozwidlenia?

chips
źródło
1
Chociaż lsjest to program zewnętrzny echo *lub echo * .*(w zależności od opcji powłoki) całkiem dobrze spisuje pliki bez rozwidlania.
gerrit
Jest jeszcze lepiej: printf "% s \ n" *
Costa
Uwaga dotycząca różnorodności powłok: tcsh ma wbudowaną funkcję, ls-Fktóra działa jak ls -F. Jest tam dla wydajności. Zawsze dostajesz, -Fco jest zwykle dobrym pomysłem. Jeśli określisz dowolne inne opcje, uruchomi się polecenie zewnętrzne.

Odpowiedzi:

18

Odpowiedź jest mniej więcej taka, lsjak zewnętrzny plik wykonywalny. Możesz zobaczyć jego lokalizację, uruchamiając type -p ls.

Dlaczego więc nie jest lswbudowany w powłokę? Dlaczego tak ma być? Zadaniem powłoki nie jest uwzględnienie wszystkich dostępnych poleceń, ale zapewnienie środowiska, w którym można je uruchomić. Niektóre współczesne powłoki mają echo, printfi ich podobne, wbudowane, które technicznie nie muszą być wbudowane, ale są tworzone ze względu na wydajność, gdy są uruchamiane wielokrotnie (głównie w ciasnych pętlach). Bez ich wbudowania powłoka musiałaby rozwidlać i wykonywać nowy proces dla każdego wywołania do nich, co może być bardzo wolne.

Przynajmniej uruchomienie lszewnętrznego pliku wykonywalnego wymaga uruchomienia jednej z rodziny wywołań systemowych exec. Możesz to zrobić bez rozwidlenia, ale zastąpiłoby to podstawową powłokę, której używasz. Aby zobaczyć, co dzieje się w tym przypadku, wykonaj następujące czynności:

exec ls; echo "this never gets printed"

Ponieważ obraz procesu powłoki został zastąpiony, bieżąca powłoka nie jest już dostępna po wykonaniu tej czynności. Aby powłoka mogła nadal działać po uruchomieniu ls, polecenie musiałoby być wbudowane w powłokę.

Forking pozwala na zastąpienie procesu, który nie jest twoją podstawową powłoką, co oznacza, że ​​możesz dalej uruchamiać swoją powłokę.

Chris Down
źródło
1
Myślę, że pyta, dlaczego ls (1) nie jest wbudowaną funkcją powłok, którą ktoś musiałby wyjaśnić, w jaki sposób różni dostawcy mają różne opcje dla ls (1) i są w stanie zapytać o różne rzeczy z systemu plików itp. A także wzloty i upadki polegające na „wbudowaniu” powłoki.
llua
@llua dodałam trochę informacji na ten temat, a wyjątkiem przypadków echo, printfitp
Chris dół
Nie zawsze jest jasne, dlaczego niektóre rzeczy są wbudowane, a inne nie. Na przykład, dlaczego cdzewnętrzny plik wykonywalny nie jest?
Faheem Mitha
@FaheemMitha Jest to zewnętrzny cdwykonywalny w POSIX systemów operacyjnych ( patrz tutaj ). Jeśli jednak chcesz faktycznie używać chdir () w bieżącym procesie, musisz go wbudować w powłokę.
Chris Down
stało się nawykiem, dlaczego lsjest zewnętrzny, ale można go również wdrożyć w powłoce. Zobacz zajęty.
15

The Bash Reference Manual stany:

Wbudowane polecenia są niezbędne do wdrożenia funkcjonalności niemożliwej lub niewygodnej do uzyskania za pomocą oddzielnych narzędzi.

Oznacza to, że pociski zostały zaprojektowane, aby tylko to wbudowanych komend, jeżeli:

  1. Wymagane przez standard POSIX
  2. Polecenia wymagające dostępu do samej powłoki, takie jak wbudowane funkcje kontroli zadań
  3. Polecenia, które są bardzo proste, niezależne od systemu operacyjnego i zwiększają wydajność wykonywania, gdy są implementowane jako wbudowane, takie jak printf

lsKomenda nie pasuje do żadnej z powyższych WYMAGANIA.

Jednak tutaj nie ma ograniczeń programistycznych, które uniemożliwiałyby lsimplementację jako wbudowanej, która działa w tym samym procesie co interpreter bash. Przyczyny projektowania poleceń, które nie są implementowane jako wbudowane powłoki:

  1. Powłoka powinna być oddzielna od systemu plików - żadne wbudowane polecenia nie powinny zależeć od poprawnego działania dowolnego systemu plików lub urządzeń peryferyjnych
  2. Polecenie, które może być zależne od systemu plików lub systemu operacyjnego, powinno być osobnym plikiem wykonywalnym
  3. Polecenie, do którego możesz chcieć przesyłać do lub z potoku, powinno być osobnym procesem
  4. Polecenie, które możesz chcieć uruchomić w tle, powinno być osobnym plikiem wykonywalnym
  5. Polecenie, które ma dużą liczbę możliwych parametrów, lepiej jest zaimplementować w osobnym pliku wykonywalnym
  6. Polecenia, które powinny mieć takie same dane wyjściowe, niezależnie od tego, jaki typ powłoki (bash, csh, tsh, ...) je wywołuje, powinny być samodzielnymi plikami wykonywalnymi

Jeśli chodzi o pierwszy powód - chcesz, aby powłoka była jak najbardziej niezależna i odporna. Nie chcesz, aby powłoka utknęła na lswierzchowcu NFS, który „nie odpowiada, wciąż próbuje”.

Jeśli chodzi o drugi powód - w wielu przypadkach możesz chcieć użyć powłoki dla systemu, który używa Busybox lub innego systemu plików, który ma inną lsimplementację. Lub nawet użyj tego samego źródła powłoki w systemach operacyjnych, które mają różne lsimplementacje.

Odnośnie trzeciego powodu - dla takich wyrażeń, find . -type d | xargs ls -ladktóre byłyby trudne lub niemożliwe do zaimplementowania lsw tym samym procesie, co interpreter powłoki.

Odnośnie czwartego powodu - wykonanie niektórych lspoleceń może zająć dużo czasu. W międzyczasie możesz chcieć, aby powłoka kontynuowała wykonywanie czegoś innego.


Uwaga: Patrz to pomocne stanowiska przez Warren Younga w odpowiedzi na podobne pytanie.

Jonathan Ben-Avraham
źródło
Brakowało ci łatwości przesyłania danych wyjściowych, jeśli jest to osobne polecenie, i całe programowanie, jakie zajmie, aby potokować operację podstawową powłoki do osobnego pliku wykonywalnego.
Bruce Ediger,
@BruceEdiger: Co za przyjemność otrzymać komentarz od cenionego BE. Dzięki! Uważam, że powód 3 obejmuje twój komentarz, nie?
Jonathan Ben-Avraham
1
Myślałem bardziej zgodnie z tym, jak skomplikowany byłby kod źródłowy samej powłoki, gdyby musiał obsługiwać potoki dla procesów zewnętrznych i potokować wyjście polecenia wewnętrznego, takiego jak hipotetyczny, lsdo procesu zewnętrznego. Można to zrobić, ale byłoby to skomplikowane.
Bruce Ediger,
1
Obawiam się, że większość, jeśli nie wszystkie z 5 punktów są dyskusyjne. 1: ls jest (mam nadzieję) niezależny od implementacji systemu plików. To zależy od jądra, aby zapewnić spójny interfejs standardowej biblioteki i aplikacji. 2: ls jest prawdopodobnie mniej zależny od systemu operacyjnego niż powłoka. 3: powłoki zdecydowanie zezwalają na wbudowane potoki. 4: powłoki zdecydowanie pozwalają na uruchamianie wbudowanych plików w tle. 5: to dość subiektywne.
jlliagre
1
@ JonathanBen-Avraham @BruceEdiger Czy powłoki nie obsługują już potoku dla poleceń wbudowanych z podpowłokami? np . bashwyjście alias | grep ls. wkładcat /etc/passwd | while read a; do echo "$a"; done
Matt
2

lsnie wymaga osobnego procesu. Bardzo niewiele poleceń wymaga osobnego procesu: tylko te, które wymagają zmiany uprawnień.

Zasadniczo powłoki implementują polecenia jako wbudowane tylko wtedy, gdy polecenia te muszą zostać zaimplementowane jako wbudowane. Polecenia jak alias, cd, exit, export, jobs, ... trzeba czytać lub modyfikować jakiś wewnętrzny stan powłoki, a zatem nie mogą być oddzielne programy. Polecenia, które nie mają takich wymagań, mogą być osobnymi poleceniami; w ten sposób można je wywoływać z dowolnej powłoki lub innego programu.

Patrząc na listę wbudowanych poleceń bash, tylko następujące wbudowane elementy mogą być zaimplementowane jako osobne polecenia. W przypadku niektórych z nich nastąpiłaby niewielka utrata funkcjonalności.

  • command- ale straci swoją przydatność w sytuacjach, w których PATHmoże nie być poprawnie skonfigurowany, a skrypt korzysta z niego commandw ramach konfiguracji.
  • echo - jest wbudowany w wydajność.
  • help - może korzystać z osobnej bazy danych, ale osadzenie tekstu pomocy w pliku wykonywalnym powłoki ma tę zaletę, że powoduje, że plik wykonywalny powłoki jest samodzielny.
  • kill - wbudowanie ma dwie zalety: oprócz identyfikatorów procesów może rozpoznać oznaczenia zadań i można go używać nawet wtedy, gdy nie ma wystarczających zasobów, aby rozpocząć osobny proces.
  • printf- z tego samego powodu echo, a także w celu obsługi -vopcji umieszczenia wyniku w zmiennej.
  • pwd - wbudowane oferuje dodatkową możliwość logicznego śledzenia bieżącego katalogu (pozostawiając nietknięte łącza symboliczne zamiast je rozszerzać).
  • test- jest wbudowanym narzędziem zwiększającym wydajność (a bash robi też magię z plikami wywoływanymi /dev/fd/…w niektórych systemach operacyjnych).

Kilka powłok oferuje znaczną liczbę dodatkowych wbudowań. Jest skrzydło , które jest powłoką zaprojektowaną jako samodzielny plik binarny do napraw awaryjnych (gdy niektóre zewnętrzne polecenia mogą nie być użyteczne). Ma wbudowane tak lszwane -ls, a także inne narzędzia, takie jak -grepi -tar. Wbudowane funkcje Sasha mają mniej możliwości niż pełnoprawne polecenia. Zsh oferuje podobne funkcje wbudowane w module zsh / files . Nie ma ls, ale interpretacja symboli wieloznacznych ( echo *) i zstatmoże pełnić podobną funkcję.

Gilles „SO- przestań być zły”
źródło
2

Myślę, że coś, czego brakuje ludziom, to złożoność lsprogramu GNU w Linuksie. Porównując wielkość wykonywalny lsdo bashi dashmuszli w moim systemie Debian, widzimy, że jest to dość duży:

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

Uwzględnienie lstak pełnej funkcjonalności jak wersja GNU bashzwiększyłoby rozmiar pliku wykonywalnego o 10%. Ma prawie taki sam rozmiar jak pełna dashskorupa!

Większość wbudowanych powłok jest wybierana, ponieważ integrują się z powłoką w sposób, którego nie mogą wykonać zewnętrzne pliki wykonywalne (pytanie to wskazuje cd, ale innym przykładem jest wersja bash killintegracji z kontrolą zadań bash) lub ponieważ są to bardzo proste polecenia do wdrożenia, dając dużą szybkość w porównaniu do wielkości ( truei falsesą tak proste, jak to tylko możliwe).

GNU lsma długi cykl rozwoju, a implementacje mogą zawierać opcje dostosowywania wyświetlanych wyników. Domyślnie użycie wbudowanego ls spowoduje utratę tej funkcjonalności lub znaczne zwiększenie złożoności i wielkości powłoki.

Graeme
źródło
1

cdjest wbudowany w powłokę, lsjest osobnym programem, który zobaczysz w /bin/ls.

DopeGhoti
źródło
0

Rób to, czego szukasz:

printf "%s\n" *

Możesz także przechowywać nazwy plików w tablicy:

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

Ale to nie obchodzi spacji w nazwach
Przechodzi do zmiennej i dba o spacje:

printf "%s\n" * | while read a; do echo $a; done
Costa
źródło