Wenn eine Shell aufgefordert wird, einen wahrscheinlich unbrauchbaren ( oder teilweise unbrauchbaren ) Befehl auszuführen, von dem bekannt ist, dass er beendet wird, wie z. B. cat hugeregularfile.txt > /dev/null
, kann sie die Ausführung dieses Befehls überspringen ( oder eine billigere Entsprechung ausführen , z. B. touch -a hugeregularfile.txt
)?
Im Allgemeinen ähnelt die Shell C-Compilern dahingehend, dass sie den Quellcode umwandeln kann, solange das von außen beobachtbare Verhalten so ist, als ob es von der abstrakten Maschine ausgewertet würde.
BEARBEITEN
Nota Bene: Meine Frage , wie ursprünglich gestellt hatte einen Titel, der Frage , ob die Schale erlaubt diese Optimierungen zu tun, nicht , ob es sein sollte oder ob Implementierungen , die sie existieren tun können. Ich interessiere mich mehr für die Theorie als für die Praxis, obwohl beide willkommen sind.
cat
es macht einen großen Unterschied. Die Shell kann erkennen, dass die Datei ein Gerät ist, sie muss jedoch nicht zuverlässig sein.wc
, zum Beispiel). Nach meinem besten Wissen bezieht POSIX jedoch keine Position in Bezug auf die Shell-Optimierung. Oder doch?ksh
. Wie sie sagen, nicht separate Prozesse, sondern Subshell-Umgebungen , um gabelsparende Optimierungen zu ermöglichen.Antworten:
Nein, das wäre eine schlechte Idee.
cat hugeregularfile.txt > /dev/null
undtouch -a hugeregularfile.txt
sind nicht dasselbe.cat
liest die gesamte Datei, auch wenn Sie die Ausgabe an umleiten/dev/null
. Und das Lesen der gesamten Datei könnte genau das sein, was Sie wollen. Zum Beispiel, um es zwischenzuspeichern, so dass spätere Lesevorgänge bedeutend schneller sind. Die Shell kann Ihre Absicht nicht erkennen.Ebenso optimiert ein C-Compiler das Lesen einer Datei nie, selbst wenn Sie sich die gelesenen Inhalte nicht ansehen.
quelle
true
undfalse
) hat potenzielle Nebenwirkungen, und die Nebenwirkungen sind fast immer der Punkt, an dem der Befehl aufgerufen wird . Die Shell konnte diese Nebenwirkungen nicht im Voraus kennen (für externe Programme wiecat
), ohne das Halteproblem zu lösen. Also versucht es das zu Recht nicht und geht davon aus, dass Sie gemeint haben, was Sie gesagt haben.cat
. In der Tatcat
könnte alles von der Formatierung Ihrer Festplatte bis zum Herunterladen des Internets getan werden.true
undfalse
eingestellt$?
.cat
und/dev/null
haben typische Bedeutungen , aber sie sind nicht garantiert verhalten , dass die Art und Weise. Um Optimierungen durchzuführen und gleichzeitig sicherzustellen, dass sich das erwartete Verhalten nicht ändert, kann die Optimierung nur mit Konstrukten durchgeführt werden, die in der Shell selbst implementiert sind, und nicht mit Dingen, die in der Ausführungsumgebung zu finden sind.Nein, da
/dev/null
es sich nur um einen Namen handelt, der für jedes andere Gerät oder für eine andere Datei als eine "normale" Datensenke verwendet werden kann.Eine Shell (oder ein anderes Programm) hat aufgrund des Namens keine Ahnung, ob die Datei, in die sie schreibt, tatsächlich etwas mit den Daten tut. Es gibt bei AFAIK auch keine Systemaufrufe, die das Shell-Programm machen kann, um festzustellen, dass zB der Dateideskriptor eigentlich nichts tut.
Ihr Vergleich mit dem Optimieren von entferntem Code in einem C-Programm funktioniert nicht, da eine Shell nicht den Gesamtüberblick hat, den ein C-Compiler über einen Teil des Quellcodes hat. Eine Shell weiß nicht genug über
/dev/null
die Optimierung Ihres Beispiels, eher wie ein C-Compiler nicht genug über den Code in einem Funktionsaufruf, mit dem sie dynamisch verknüpft ist, um den Aufruf nicht auszuführen.quelle
/dev/null
manchmal speziell behandeln . Ein Builtin, dessen Standardausgabe/dev/null
z. B. an gerichtet istecho foo >/dev/null
, führt nicht dazu, dass Schreibvorgänge ausgeführt werden/dev/null
. Es macht nichts Besonderes, wenn es einen nicht eingebauten Befehl (wiecat file >/dev/null
) aufruft .cat
könnte es auch etwas anderes sein. Alles andere in der Tat./dev/null
ist einer der wenigen standardisierten Wege , zusammen mit/dev/tty
,/dev/console
,/tmp
,/dev/
und/
.cat
ist ein ksh93 eingebaut (nicht aktiviert, es sei denn, Sie setzen/opt/ast/bin
vorher/bin
(oder wo immer welchecat
verfügbar sind) in$PATH
). Und ja, obwohlcat file > /dev/null
das eingebaute Programmread
den Inhalt von ausführt, schreibtfile
es ihn nicht nach / dev / null (obwohl es geöffnet und gestartet wird).Laufende Befehle werden nicht optimiert (und Sie haben bereits eine Reihe guter Antworten erhalten, in denen erklärt wird, warum dies nicht der Fall sein sollte). In einigen Fällen werden jedoch möglicherweise Gabeln, Pipe- / Socket-Paare und Lesevorgänge optimiert. Welche Optimierungen es machen kann:
trap
s festgelegt wurden. Zum Beispiel in densh -c ls
meistsh
Implementierungen (bash
,mksh
,ksh
,zsh
,yash
, einige Versionen vonash
) nicht , ein Verfahren zur Lauf gabelnls
.ksh93
wird durch die Befehlssubstitution erst dann ein Pipe- oder Fork- Prozess erstellt, wenn ein externer Befehl aufgerufen wird ($(echo foo)
beispielsweisefoo
ohne Pipe / Socket-Paar oder Fork).read
eingebauten Shells (bash
, AT & Tksh
) führen keine Einzelbyte-Lesevorgänge durch, wenn sie feststellen, dass stdin suchbar ist (in diesem Fall führen sie große Lesevorgänge durch und suchen bis zum Ende des Lesevorgangs zurück).quelle
ksh93
Ist die Shell führend bei der Optimierung, da das Ziel / die Aufgabe darin bestand, Programmiersprachen wieperl
. Sie können sich also dieksh
Dokumentation, den Code (viel Glück) und die Mailingliste ansehen , um weitere Informationen zu erhalten.sh -c 'ps -p "$$"'
was Sie gebenps
und nichtsh
mit diesensh
Implementierungen oder mit strace / truss / tusc ...ksh -c 'ps; ps'
und bash -c 'ps; ps' ist interessant. Ksh93 geht in seiner Optimierung weiter.ksh
hier die Rede ist.mksh
benimmt sich wiebash
. Dieses Verhalten ist hauptsächlich dazu gedacht, Dinge wie zu optimierensystem("some command")
. Beachten Sie, dass diese Optimierung einen Nebeneffekt hat, wenn es um den Beendigungsstatus von Prozessen geht, die durch ein Signal (in einigen Shells) beendet werden.ksh93
Früher hatte es den Fehler, dass es die Optimierung selbst dann durchführte, wenn Traps gesetzt waren.Beim Sehen
cat hugeregularfile.txt > /dev/null
darf die Shell nicht glauben, dass die Aktion nutzlos ist - siecat
ist kein Teil der Shell und kann theoretisch und auch praktisch alles Mögliche tun.Beispielsweise kann der Benutzer die ausführbare Datei
rm
in umbenannt habencat
, und die Zeile führt plötzlich ein extern beobachtbares Verhalten aus, dh das Entfernen der Datei.Der Benutzer hat möglicherweise eine Version kompiliert
cat
, die in eine Endlosschleife übergeht. Daher kann die Shell nicht davon ausgehen, dass bekannt ist, dass sie beendet wird, wie Sie vorschlagen.Jemand hat möglicherweise eine Version davon installiert
cat
, die wie beabsichtigt funktioniert, aber mit dem zusätzlichen Nebeneffekt, dass ein Rootkit installiert wird, falls es jemals mit angemessenen Berechtigungen ausgeführt wird. Auch hier sollte die Shell dies ordnungsgemäß ausführen.quelle
mksh
Tatsächlich optimiertV=$(cat file)
es tatsächlich, indem es ein eingebautes macht. Die Shell kann es also optimieren, aber nicht nur in a umwandelntouch -a
.cat
ist ein builtin inmksh
, aber das builtin Resorts auf das System ist ,cat
wenn eine Option übergeben, weshalb mit GNU istcat
,mksh -c 'cat /dev/null --help'
führt nicht das gleiche Ergebnis wiebash -c 'cat /dev/null --help'
, abermksh -c 'cat --help /dev/null'
Ihnen nicht gibt das gleiche wiebash -c 'cat --help /dev/null'
(wiemksh
cat builtin Parsen Optionen die POSIX Art und Weise, während GNU cat sie auf die GNU-Art und Weise analysiert).V=$(cat file)
kann das mit optimiert werdenV=$(< file)
. Dies beschleunigt die Dinge auch ohne eingebautescat
.