Warum ist ls
für die Ausführung ein separater Prozess erforderlich? Ich kenne den Grund, warum Befehle wie cd
nicht mit dem Gabelmechanismus ausgeführt werden können, aber kann es schaden, wenn ls
sie ohne Gabeln ausgeführt werden?
Warum ist ls
für die Ausführung ein separater Prozess erforderlich? Ich kenne den Grund, warum Befehle wie cd
nicht mit dem Gabelmechanismus ausgeführt werden können, aber kann es schaden, wenn ls
sie ohne Gabeln ausgeführt werden?
Antworten:
Die Antwort ist mehr oder weniger ls
eine externe ausführbare Datei. Sie können die Position anzeigen, indem Sie ausführen type -p ls
.
Warum ist ls
die Shell dann nicht eingebaut? Nun, warum sollte es sein? Die Aufgabe einer Shell besteht nicht darin, jeden verfügbaren Befehl zu umfassen, sondern eine Umgebung bereitzustellen, in der sie ausgeführt werden kann. Einige moderne Schalen haben echo
, printf
und Konsorten als builtins, die nicht technisch builtins sein müssen, sind aber so aus Performance - Gründen gemacht , wenn sie wiederholt ausgeführt werden (vor allem in engen Schleifen). Ohne sie zu integrieren, müsste die Shell für jeden Aufruf einen neuen Prozess ausgeben und ausführen, was extrem langsam sein kann.
Um ls
eine externe ausführbare Datei auszuführen, muss mindestens eine der Systemaufrufe der exec-Familie ausgeführt werden. Sie könnten dies ohne Gabeln tun, aber es würde die primäre Shell ersetzen, die Sie verwenden. Sie können sehen, was in dieser Instanz passiert, indem Sie wie folgt vorgehen:
exec ls; echo "this never gets printed"
Da das Prozessabbild Ihrer Shell ersetzt wird, ist die aktuelle Shell danach nicht mehr erreichbar. Damit die Shell nach dem Ausführen von ls weiter ausgeführt werden kann, muss der Befehl in die Shell integriert werden.
Durch das Verzweigen kann ein Prozess ersetzt werden, der nicht Ihre primäre Shell ist, sodass Sie Ihre Shell anschließend weiter ausführen können.
echo
, printf
usw.
cd
keine externe ausführbare Datei?
cd
ausführbare Datei vorhanden ( siehe hier ). Wenn Sie jedoch tatsächlich chdir () im aktuellen Prozess verwenden möchten, müssen Sie es in die Shell integrieren.
Im Bash-Referenzhandbuch heißt es:
Integrierte Befehle sind erforderlich, um Funktionen zu implementieren, die mit separaten Dienstprogrammen nicht oder nur schwer zu erhalten sind.
Das heißt, Shells enthalten nur dann eingebaute Befehle, wenn:
Der ls
Befehl entspricht keiner der oben genannten Anforderungen.
Allerdings , hier ist keine Programmierung Einschränkung , die verhindern würde ls
als Einbau in wobei implmented, die sich im selben Prozess wie der Bash - Interpreter ausgeführt wird . Die Entwurfsgründe für Befehle, die nicht als Shell-Einbauten implementiert werden, sind:
Zum ersten Grund: Sie möchten, dass die Shell so unabhängig und widerstandsfähig wie möglich ist. Sie möchten nicht, dass die Shell an ls
einem NFS-Mount hängen bleibt, der "immer noch nicht antwortet".
Zum zweiten Grund: In vielen Fällen möchten Sie möglicherweise eine Shell für ein System verwenden, das Busybox oder ein anderes Dateisystem mit einer anderen ls
Implementierung verwendet. Oder verwenden Sie in Betriebssystemen mit unterschiedlichen ls
Implementierungen dieselbe Shell-Quelle .
Zum dritten Grund - Für Ausdrücke wie find . -type d | xargs ls -lad
wäre es schwierig oder unmöglich, die ls
im gleichen Prozess wie der Shell-Interpreter zu implementieren .
Zum vierten Grund - Die ls
Ausführung einiger Befehle kann einige Zeit in Anspruch nehmen. Vielleicht möchten Sie, dass die Shell in der Zwischenzeit noch etwas anderes ausführt.
Hinweis: Siehe diesen hilfreichen Beitrag von Warren Young als Antwort auf eine ähnliche Frage.
ls
in einen externen Prozess umleiten müsste . Es könnte getan werden, aber es wäre kompliziert.
bash
Ausgabe alias | grep ls
. Eingabecat /etc/passwd | while read a; do echo "$a"; done
ls
erfordert keinen separaten Prozess. Nur sehr wenige Befehle erfordern einen separaten Prozess: Nur diejenigen, die Berechtigungen ändern müssen.
In der Regel implementieren Shells Befehle nur dann als integrierte Befehle, wenn diese Befehle als integrierte Befehle implementiert werden müssen. Befehle wie alias
, cd
, exit
, export
, jobs
, ... muß einigen internen Zustand der Schale lesen oder zu ändern, und kann daher nicht getrennte Programme sein. Befehle ohne solche Anforderungen können separate Befehle sein. Auf diese Weise können sie von jeder Shell oder einem anderen Programm aus aufgerufen werden.
Betrachtet man die Liste der Buildins in Bash, so können nur die folgenden Buildins als separate Befehle implementiert werden. Für einige von ihnen würde es einen leichten Funktionsverlust geben.
command
- aber es würde seine Nützlichkeit in Situationen verlieren, in denen es PATH
möglicherweise nicht richtig eingerichtet ist und das Skript es command
als Teil der Einrichtung verwendet.echo
- Es ist ein fester Bestandteil der Effizienz.help
- Es könnte eine separate Datenbank verwendet werden, aber das Einbetten des Hilfetexts in die ausführbare Shell-Datei hat den Vorteil, dass die ausführbare Shell in sich geschlossen ist.kill
- Ein integrierter Prozess bietet zwei Vorteile: Er kann neben Prozess-IDs auch Job-Bezeichnungen erkennen und verwendet werden, selbst wenn nicht genügend Ressourcen zum Starten eines separaten Prozesses vorhanden sind.printf
- Aus dem gleichen Grund wie echo
und um die -v
Option zu unterstützen, die Ausgabe in eine Variable zu setzen.pwd
- Das eingebaute Modul bietet die zusätzliche Möglichkeit, das aktuelle Verzeichnis logisch zu verfolgen (wobei symbolische Verknüpfungen intakt bleiben, anstatt sie zu erweitern).test
- Es ist aus Effizienzgründen eingebaut (und Bash macht auch etwas Magie mit Dateien, die /dev/fd/…
auf einigen Betriebssystemen aufgerufen werden).Einige wenige Muscheln bieten eine erhebliche Anzahl zusätzlicher eingebauter Komponenten. Es gibt Sash , eine Shell, die als eigenständige Binärdatei für Notfallreparaturen entwickelt wurde (wenn einige externe Befehle möglicherweise nicht verwendet werden können). Es hat ein eingebautes ls
, genanntes -ls
, sowie andere Tools wie -grep
und -tar
. Die eingebauten Funktionen von Sash sind weniger leistungsfähig als die vollwertigen Befehle. Zsh bietet einige ähnliche integrierte Funktionen in seinem Modul zsh / files an . Es hat keine ls
, aber Wildcard-Erweiterung ( echo *
) und zstat
kann eine ähnliche Funktion erfüllen.
Ich denke, dass hier etwas fehlt, was die Scherkomplexität des GNU- ls
Programms unter Linux ist. Vergleicht man die ausführbare Größe von ls
mit bash
und dash
Shells auf meinem Debian-System, so sieht man, dass es ziemlich groß ist:
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
Das Einbeziehen einer ls
so umfassenden Version wie die GNU-Version in bash
würde die ausführbare Größe um 10% erhöhen. Es ist fast so groß wie die ganze dash
Schale!
Die meisten Shell-Buildins werden ausgewählt, weil sie sich so in die Shell integrieren lassen, wie es externe ausführbare Dateien nicht können (die Frage zeigt cd
, aber ein anderes Beispiel ist die Bash-Version der kill
Integration in die Bash-Job-Steuerung) oder weil sie sehr einfach zu implementierende Befehle sind. eine große Geschwindigkeit gegen Größe auszahlen ( true
und false
sind so einfach wie es nur geht).
GNU ls
hatte einen langen Entwicklungszyklus und implementiert möglicherweise Optionen, um anzupassen, welche / wie Ergebnisse angezeigt werden. Die Verwendung eines integrierten Betriebssystems würde entweder diese Funktionalität verlieren oder die Komplexität und Größe der Shell erheblich erhöhen.
Das tun, wonach Sie suchen:
printf "%s\n" *
Sie können auch Dateinamen im Array speichern:
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
Leerzeichen in Namen sind ihm jedoch egal.
Dies wird an Variable übergeben und Leerzeichen sind wichtig:
printf "%s\n" * | while read a; do echo $a; done
ls
es sich um ein externes Programm handelt,echo *
oderecho * .*
(abhängig von den Shell-Optionen) Dateien ziemlich gut auflistet, ohne zu forken.