Jeśli powłoka zostanie poproszona o wykonanie prawdopodobnie bezużytecznej ( lub częściowo bezużytecznej ) komendy, o której wiadomo, że kończy działanie, na przykład cat hugeregularfile.txt > /dev/null
, czy może pominąć wykonanie tej komendy ( lub wykonać tańszy odpowiednik, powiedzmy, touch -a hugeregularfile.txt
)?
Mówiąc bardziej ogólnie, czy powłoka jest podobna do kompilatorów C pod tym względem, że może wykonywać dowolną transformację w kodzie źródłowym, o ile obserwowane z zewnątrz zachowanie jest tak, jakby maszyna abstrakcyjna go oceniała?
EDYTOWAĆ
Nota Bene: Moje pierwotnie postawione pytanie miało tytuł, w którym zapytano, czy powłoka może wykonywać te optymalizacje, a nie to, czy powinna, a nawet czy istnieją implementacje, które mogą je wykonać. Teoria interesuje mnie bardziej niż praktyka, chociaż obie są mile widziane.
cat
ting robi dużą różnicę. Powłoka może dowiedzieć się, że plik jest urządzeniem, ale nie musi być niezawodny.wc
, na przykład). Ale według mojej najlepszej wiedzy POSIX nie zajmuje stanowiska w sprawie optymalizacji powłoki; A może to?ksh
. Jakby nie mówili o oddzielnym procesie, ale o środowisku podpowłoki, aby umożliwić optymalizację oszczędzania widelca.Odpowiedzi:
Nie, to byłby zły pomysł.
cat hugeregularfile.txt > /dev/null
itouch -a hugeregularfile.txt
nie są takie same.cat
odczyta cały plik, nawet jeśli przekierujesz wyjście do/dev/null
. A odczytanie całego pliku może być dokładnie tym, czego chcesz. Na przykład w celu buforowania, aby późniejsze odczyty były znacznie szybsze. Powłoka nie może poznać twojego zamiaru.Podobnie, kompilator C nigdy nie zoptymalizuje odczytu pliku, nawet jeśli nie spojrzysz na rzeczy, które czytasz.
źródło
true
ifalse
) ma potencjalne skutki uboczne, a efekty uboczne są prawie zawsze celem wywołania polecenia. Powłoka nie mogła z góry poznać tych skutków ubocznych (dla programów zewnętrznych, takich jakcat
) bez rozwiązania problemu zatrzymania. Więc słusznie nie próbuje i zakłada, że miałeś na myśli to, co powiedziałeś.cat
. W rzeczywistościcat
może zrobić wszystko, od sformatowania dysku twardego do pobierania Internetu.true
ifalse
ustaw$?
.cat
i/dev/null
mają typowe znaczenia, ale nie są one gwarantowane , aby zachowywać się w ten sposób. Aby przeprowadzić optymalizacje, gwarantując bez zmian oczekiwane zachowanie, optymalizacja może być dozwolona tylko przy użyciu konstrukcji zaimplementowanych w samej powłoce, a nie elementów znalezionych w środowisku wykonawczym ... bez względu na to, jak intuicyjnie mogą wyglądać ich nazwy.Nie, ponieważ
/dev/null
jest to tylko nazwa, której można użyć dla dowolnego innego urządzenia lub pliku innego niż „normalnie” ujście danych.Zatem powłoka (lub jakikolwiek inny program) nie ma pojęcia, na podstawie nazwy, czy plik, do którego pisze, robi coś „naprawdę” z danymi. AFAIK również nie wywołuje żadnych wywołań systemowych, które program powłoki może wykonać, aby ustalić, że np. Deskryptor pliku w rzeczywistości nic nie robi.
Twoje porównanie z optymalizacją kodu wyjściowego w programie C nie działa, ponieważ powłoka nie ma pełnego przeglądu, jaki kompilator C ma nad fragmentem kodu źródłowego. Powłoka nie wie wystarczająco dużo,
/dev/null
aby zoptymalizować twój przykład, bardziej jak kompilator C nie wie wystarczająco dużo o kodzie w wywołaniu funkcji, do której dynamicznie się łączy, aby nie wykonać wywołania.źródło
/dev/null
specjalnie. Wbudowanym poleceniem, które jego stdout skierowany do/dev/null
, na przykładecho foo >/dev/null
, nie spowoduje jakichkolwiek zapisów robi się/dev/null
. Nie robi nic specjalnego, jeśli wywołuje niewbudowane polecenie (takie jakcat file >/dev/null
).cat
może być coś innego. Cokolwiek innego w rzeczywistości./dev/null
jest jednym z niewielu standardowych ścieżek , wraz z/dev/tty
,/dev/console
,/tmp
,/dev/
i/
.cat
jest wbudowany w ksh93 (nie jest włączony, chyba że włożysz go/opt/ast/bin
wcześniej/bin
(lub gdziekolwiekcat
jest dostępny$PATH
). I tak, chociażcat file > /dev/null
z tym wbudowanym robiread
zawartośćfile
, nie zapisuje go do / dev / null (chociaż otwiera się i fstats to).Nie zoptymalizuje uruchomionych poleceń (a otrzymałeś już wiele drobnych odpowiedzi, które mówią ci, dlaczego nie powinien), ale może zoptymalizować rozwidlenia, pary rur / gniazd, w niektórych przypadkach czyta. Rodzaj optymalizacji, jakie może on wykonać:
trap
zostały ustawione. Na przykład, wsh -c ls
, większoścish
implementacji (bash
,mksh
,ksh
,zsh
,yash
, w niektórych wersjachash
) nie rozwidla procesu w celu uruchomienials
.ksh93
, podstawienie polecenia nie utworzy potoku ani nie rozwidli procesu, dopóki nie zostanie wywołane polecenie zewnętrzne ($(echo foo)
na przykład zostanie rozszerzonefoo
bez pary potoku / gniazda lub rozwidlenia).read
wbudowane w niektórych muszli (bash
AT & Tksh
) nie zrobi jednobajtowe czyta jeśli wykryje stdin jest możliwy do przeszukania (w takim przypadku będą robić duże czyta i dążyć z powrotem do końca, co oni mają do odczytu).źródło
ksh93
jest powłoką wiodącą na froncie optymalizacji, ponieważ jej celem jest / miało być postrzegane jako dorównujące językom programowania takim jakperl
. Możesz więc zajrzeć doksh
dokumentacji, kodu (powodzenia) i listy mailingowej w celu uzyskania dalszych informacji.sh -c 'ps -p "$$"'
co da ci,ps
a nie zash
pomocą tychsh
implementacji, lub za pomocą strace / truss / tusc ...ksh -c 'ps; ps'
i bash -c 'ps; ps' jest interesująca. Ksh93 idzie dalej w zakresie optymalizacji.ksh
tutaj mówimy.mksh
zachowuje się jakbash
. Takie zachowanie ma głównie na celu optymalizację takich rzeczysystem("some command")
. Zauważ, że efektem ubocznym tej optymalizacji jest status wyjścia procesów zakończonych sygnałem (w niektórych powłokach).ksh93
Kiedyś miał błąd polegający na tym, że optymalizował nawet wtedy, gdy ustawiono pułapki.Widząc
cat hugeregularfile.txt > /dev/null
, powłoka nie może uwierzyć, że akcja jest bezużyteczna -cat
nie jest częścią powłoki i mogłaby w ogóle zrobić wszystko w teorii, a także w praktyce.Na przykład, użytkownik może mieć przemianowany plik wykonywalny
rm
docat
i nagle wykonuje linia zewnętrznie obserwowalne zachowanie, czyli usunięcie pliku.Użytkownik mógł skompilować wersję,
cat
która przechodzi w nieskończoną pętlę, więc powłoka nie może zakładać, że „wiadomo, że kończy się”, jak sugerujesz.Ktoś mógł zainstalować wersję,
cat
która działa zgodnie z przeznaczeniem, ale z dodatkowym efektem ubocznym instalowania rootkita, jeśli kiedykolwiek będzie działał z odpowiednimi uprawnieniami - ponownie powłoka powinna go należycie wykonać.źródło
mksh
rzeczywistości optymalizujeV=$(cat file)
, czyniąc go wbudowanym. Więc powłoka może ją zoptymalizować, ale nie przekształcić jej w tylkotouch -a
.cat
jest wbudowanym poleceniem wmksh
, ale to ośrodki wbudowane do systemucat
, jeśli przekazywane żadnej opcji, dlatego z GNUcat
,mksh -c 'cat /dev/null --help'
nie daje taki sam wynik jakbash -c 'cat /dev/null --help'
, alemksh -c 'cat --help /dev/null'
nie daje to samo cobash -c 'cat --help /dev/null'
(jakmksh
kot wbudowanym analizuje możliwości POSIX sposób, podczas gdy kot GNU analizuje je w sposób GNU).V=$(cat file)
można to zoptymalizować za pomocąV=$(< file)
. Przyspiesza to rzeczy nawet bez wbudowanegocat
.