gnu bourne again shell
DESCRIPTION
Presentation slides from a lecture on "Operating Systems" (Betriebssysteme) at FH Giessen-Friedberg (Germany).TRANSCRIPT
GNU Bourne-Again SHellEine Einfuhrung
Michele Corazza, Fabian Becker
FH Giessen-Friedberg
18. Oktober 2010
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Die GNU-POSIX-Shell BASH
Kommandozeileninterpreter
eine von vielen Shells
nur ein Programm..
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Funktionen der Bash
ausfuhren von Programmen
einzelnmehrere gleichzeitigmit Abhangigkeiten..
Operatoren
”;“ sequenziell: ls ; pwd
”&&“ ausfuhren bei Erfolg: g++ pipe.cc -o pipe && ./pipe
”‖“ ausfuhren bei Misserfolg: test -d dir ‖ mkdir dir
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Interne Bash Kommandos
intern
”cd“ wechselt das Verzeichniss
extern
”pwd“ zeigt den aktuellen Verzeichnisspfad
Test
”whereis <Programm>“
whereis cd =>cd:whereis pwd =>pwd: /bin/pwd
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Exit Codes
Konventionen
0 = Alles OK
>0 = Fehler
Ausgabe des letzten Exit Codes
echo $?
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Weitere Shell Funktionen - Shellprogrammierung
Shebang #!/bin/sh
if, while, for, case
Warum Shell Scripting?
Automatisierte Verarbeitung von Daten (Batch)
Filtern
Weitere Shell Kommandos
$1 $2 $3 Erster Zweiter Dritter Ubergabeparameter$# Anzahl der Ubergabeparameter
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ein / Ausgabe Strome
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ein / Ausgabe Umlenkung
Warum?
Fehlerausgabe in externe Datei lenken
Ausgabe des Programmes unterdrucken
Eingabe des Programmes per Datei (automatischeVerarbeitung)
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ein / Ausgabe Umleitung in der Shell
Standard Ausgabe Umlenken >
Standard Eingabe Umlenken <
Standard Fehler Umlenken 2>
Datei erstellen / anfugen
Beispiel: ls /home > dateixyan Datei anfugen: ls /home >> dateixy
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ein / Ausgabe Umleitung in C++
Ein / Ausgabe Streams sind Filedeskriptoren (0,1,2)
Unix/Linux alles ist eine Datei
werden als normale ints behandelt
Umlenkung per dup/dup2
dup2 Syntax
int dup2(int oldfd, int newfd)
Ruckgabewert: der neue Filedeskriptor
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Pipeline
Unnamed Pipes
Standard Pipes in C/C++
haben keinen Filedeskriptor
kommen zum Einsatz wenn ein Kindprozess in die Pipeschreiben soll
Named Pipes
haben einen globalen Verzeichnis Eintrag
werden immer dann gebraucht wenn die Prozesse unabhangigvoneinader sind (kein Fork())
pipe C-Call
int fd[2];
pipe(fd);
fd[0] lesen, fd[1] schreiben
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Systemcall fork()
Eigenschaften von fork()
Erstellt eine Kopie des Prozesses
Aufrufender Prozess wird”parent“ genannt, die Kopie
”child“
fork() liefert im parent die PID des Kindprozesses, imKindprozess 0 zuruck
Kann fork() fehlschlagen? Wenn ja, wann?
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Systemcall fork()
Eigenschaften von fork()
Erstellt eine Kopie des Prozesses
Aufrufender Prozess wird”parent“ genannt, die Kopie
”child“
fork() liefert im parent die PID des Kindprozesses, imKindprozess 0 zuruck
Kann fork() fehlschlagen? Wenn ja, wann?
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Systemcall fork()
Eigenschaften von fork()
Erstellt eine Kopie des Prozesses
Aufrufender Prozess wird”parent“ genannt, die Kopie
”child“
fork() liefert im parent die PID des Kindprozesses, imKindprozess 0 zuruck
Kann fork() fehlschlagen? Wenn ja, wann?
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Systemcall fork()
Eigenschaften von fork()
Erstellt eine Kopie des Prozesses
Aufrufender Prozess wird”parent“ genannt, die Kopie
”child“
fork() liefert im parent die PID des Kindprozesses, imKindprozess 0 zuruck
Kann fork() fehlschlagen? Wenn ja, wann?
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Fehlschlagen von fork()
fork() kann fehlschlagen, wenn..
nicht genugend freier Arbeitspeicher verfugbar ist (EAGAIN)
das Prozesslimit des Benutzers erreicht wurde (EAGAIN)
die notigen Kernelstrukturen nicht allokiert werden konnten(ENOMEM)
In diesen Fallen liefert fork() -1 im parent zuruck und es wird keinKindprozess erstellt.
”errno“ wird entsprechend gesetzt.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Fehlschlagen von fork()
fork() kann fehlschlagen, wenn..
nicht genugend freier Arbeitspeicher verfugbar ist (EAGAIN)
das Prozesslimit des Benutzers erreicht wurde (EAGAIN)
die notigen Kernelstrukturen nicht allokiert werden konnten(ENOMEM)
In diesen Fallen liefert fork() -1 im parent zuruck und es wird keinKindprozess erstellt.
”errno“ wird entsprechend gesetzt.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Fehlschlagen von fork()
fork() kann fehlschlagen, wenn..
nicht genugend freier Arbeitspeicher verfugbar ist (EAGAIN)
das Prozesslimit des Benutzers erreicht wurde (EAGAIN)
die notigen Kernelstrukturen nicht allokiert werden konnten(ENOMEM)
In diesen Fallen liefert fork() -1 im parent zuruck und es wird keinKindprozess erstellt.
”errno“ wird entsprechend gesetzt.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Beispiel
Listing 1: Einfaches fork() Beispiel
1 #inc lude <un i s t d . h>2 #inc lude < s t d l i b . h>3 #inc lude <s t d i o . h>4 #inc lude <s y s / t yp e s . h>56 i n t main ( vo id ) {7 p i d t f o r k p i d ;8 switch ( f o r k p i d=f o r k ( ) ) {9 case −1: p r i n t f ( ” F e h l e r b e i f o r k !\ n” ) ;
10 e x i t ( 1 ) ;11 case 0 : p r i n t f ( ”Kind : PID=%d\n” , g e t p i d ( ) ) ;12 p r i n t f ( ”Kind : E l t e r n−PID=%d\n” , g e t pp i d ( ) ) ;13 break ;14 de f au l t : p r i n t f ( ” E l t e r n p r o z . : Kind−PID=%d\n” , f o r k p i d ) ;15 }1617 e x i t ( 0 ) ;18 }
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ausgabe
Ausgabe
Elternproz.: Kind-PID=18426Kind: PID=18426Kind: Eltern-PID=18425
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Kopiervorgang
Was passiert beim Kopieren?
Variablenwerte sind identisch
Gleicher Programmzahler
Gleiche Dateideskriptoren (!)
Gleiche Zugriffsrechte / Eigentumer
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Kopiervorgang
Was passiert beim Kopieren?
Variablenwerte sind identisch
Gleicher Programmzahler
Gleiche Dateideskriptoren (!)
Gleiche Zugriffsrechte / Eigentumer
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Kopiervorgang
Was passiert beim Kopieren?
Variablenwerte sind identisch
Gleicher Programmzahler
Gleiche Dateideskriptoren (!)
Gleiche Zugriffsrechte / Eigentumer
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Kopiervorgang
Was passiert beim Kopieren?
Variablenwerte sind identisch
Gleicher Programmzahler
Gleiche Dateideskriptoren (!)
Gleiche Zugriffsrechte / Eigentumer
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Kopiervorgang
Was passiert beim Kopieren?
Variablenwerte sind identisch
Gleicher Programmzahler
Gleiche Dateideskriptoren (!)
Gleiche Zugriffsrechte / Eigentumer
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ausfuhren eines neuen Programms
exec()
Mit den exec-Funktionen wird ein neues Programm ausgefuhrt
Kein neuer Prozess! Das alte Programm wird im Speicherersetzt.
Keine Ruckkehr zum aufrufenden Programm.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ausfuhren eines neuen Programms
exec()
Mit den exec-Funktionen wird ein neues Programm ausgefuhrt
Kein neuer Prozess! Das alte Programm wird im Speicherersetzt.
Keine Ruckkehr zum aufrufenden Programm.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ausfuhren eines neuen Programms
exec()
Mit den exec-Funktionen wird ein neues Programm ausgefuhrt
Kein neuer Prozess! Das alte Programm wird im Speicherersetzt.
Keine Ruckkehr zum aufrufenden Programm.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Ausfuhren eines neuen Programms
exec()
Mit den exec-Funktionen wird ein neues Programm ausgefuhrt
Kein neuer Prozess! Das alte Programm wird im Speicherersetzt.
Keine Ruckkehr zum aufrufenden Programm.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execl()
Ausfuhrung von execl()
int execl(const char *path, const char *arg, . . .); // unistd.h
Aufruf: execl(”ls“,
”ls“,
”-al“,
”/home“, (char *)NULL);
Variable Anzahl an Parametern!
Aufruf scheitert vermutlich, da execl nur im lokalenVerzeichnis nach ls sucht.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execl()
Ausfuhrung von execl()
int execl(const char *path, const char *arg, . . .); // unistd.h
Aufruf: execl(”ls“,
”ls“,
”-al“,
”/home“, (char *)NULL);
Variable Anzahl an Parametern!
Aufruf scheitert vermutlich, da execl nur im lokalenVerzeichnis nach ls sucht.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execl()
Ausfuhrung von execl()
int execl(const char *path, const char *arg, . . .); // unistd.h
Aufruf: execl(”ls“,
”ls“,
”-al“,
”/home“, (char *)NULL);
Variable Anzahl an Parametern!
Aufruf scheitert vermutlich, da execl nur im lokalenVerzeichnis nach ls sucht.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execl()
Ausfuhrung von execl()
int execl(const char *path, const char *arg, . . .); // unistd.h
Aufruf: execl(”ls“,
”ls“,
”-al“,
”/home“, (char *)NULL);
Variable Anzahl an Parametern!
Aufruf scheitert vermutlich, da execl nur im lokalenVerzeichnis nach ls sucht.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execl()
Ausfuhrung von execl()
int execl(const char *path, const char *arg, . . .); // unistd.h
Aufruf: execl(”ls“,
”ls“,
”-al“,
”/home“, (char *)NULL);
Variable Anzahl an Parametern!
Aufruf scheitert vermutlich, da execl nur im lokalenVerzeichnis nach ls sucht.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execlp()
execlp()
Bei execl() muss immer der gesammte Pfad angegebenwerden.
int execlp(const char *file, const char *arg, . . .);
Sucht zusatzlich noch im PATH.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execlp()
execlp()
Bei execl() muss immer der gesammte Pfad angegebenwerden.
int execlp(const char *file, const char *arg, . . .);
Sucht zusatzlich noch im PATH.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execlp()
execlp()
Bei execl() muss immer der gesammte Pfad angegebenwerden.
int execlp(const char *file, const char *arg, . . .);
Sucht zusatzlich noch im PATH.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
execlp()
execlp()
Bei execl() muss immer der gesammte Pfad angegebenwerden.
int execlp(const char *file, const char *arg, . . .);
Sucht zusatzlich noch im PATH.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
exec*()
Listing 2: exec-Funktionen
1 #inc lude <un i s t d . h>23 extern char ∗∗ e n v i r o n ;4 i n t e x e c l ( const char ∗path , const char ∗ arg0 , . . . /∗ ,5 ( cha r ∗)0 ∗/ ) ;6 i n t execv ( const char ∗path , char ∗ const a rgv [ ] ) ;7 i n t e x e c l e ( const char ∗path , const char ∗ arg0 , . . . /∗ ,8 ( cha r ∗ )0 , cha r ∗ con s t envp [ ] ∗/ ) ;9 i n t execve ( const char ∗path , char ∗ const a rgv [ ] ,
10 char ∗ const envp [ ] ) ;11 i n t e x e c l p ( const char ∗ f i l e , const char ∗ arg0 , . . . /∗ ,12 ( cha r ∗)0 ∗/ ) ;13 i n t execvp ( const char ∗ f i l e , char ∗ const a rgv [ ] ) ;
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Warten auf den Kindprozess
Die Funktion waitpid()
pid t waitpid(pid t pid, int status, int options);
Warten auf Subprozessterminierung
Durch Optionen lasst sich abfragen ob ein Subprozessterminiert ist ohne dabei zu blockieren.
Durch Makros aus wait.h lassen sich Terminierungsstatusabfragen.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Abfragen des Terminierungsstatus
Makros fur waitpid()
waitpid(kind pid, &kind status, 0);
WIFEXITED(kind status) ⇒ Normal Terminiert?
WIFSIGNALED(kind status) ⇒ Terminiert durch Signal?
WTERMSIG(kind status) ⇒ Welches Signal? (numerisch)
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Zombies!
Was sind Zombies?
Prozess hat Ausfuhrung beendet
Eintrag in der Prozesstabelle ist noch vorhanden!
Wie wird man Zombies los?
Abfrage des Terminierungsstatus durch wait/waitpid
Kann mit Signals (SIGCHLD) vereinfacht werden.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell
Zombies!
Was sind Zombies?
Prozess hat Ausfuhrung beendet
Eintrag in der Prozesstabelle ist noch vorhanden!
Wie wird man Zombies los?
Abfrage des Terminierungsstatus durch wait/waitpid
Kann mit Signals (SIGCHLD) vereinfacht werden.
Michele Corazza, Fabian Becker GNU Bourne-Again SHell