ein Kapitel zurück                                           ein Kapitel weiter

Die exec-Funktionen (execute) laden und starten ein anderes Programm. Somit ersetzt das neue Programm den laufenden Prozeß vollkommend. Das neue Programm beginnt seine Ausführung in der main - Funktion. Sämtliche durch das aufrufende Programm eröffnete Dateien bleiben geöffnet. Sie stehen damit auch dem neuen Programm zur Verfügung. Folgende 6 verschiedene exec-Funktionen stehen zur Verfügung...

#include <unistd.h>

int execl(char *name, char *arg0, ... /*NULL*/);
int execv(char *name, char *argv[]);
int execle(char *name, char *arg0, ... /*,NULL, char *envp[]*/);
int execve(char *name, char *arv[], char *envp[]);
int execlp(char *name, char *arg0, ... /*NULL*/);
int execvp(char *name, char *argv[]);  

Ein exec - Aufruf bewirkt somit das über das Argument übergebene Programm, in den Speicher geladen wird, und zwar über das alte Programm, das die exec - Funktion aufruft. Das alte Programm ist somit nicht mehr verfügbar da die Segmente durch das neue Programm überschrieben wurden.

Die Buchstaben l,v,p und e am Ende der Funktionsnamen bestimmen das Format und den Umfang der Argumente, sowie die Directorys, in denen das zu ladende Programm zu suchen ist.

Buchstabe

Bedeutung

l (list) Die Argumente aus der Kommandozeile werden in der Form einer Liste arg0,arg1,....argn,NULL übergeben. Diese Form verwendet man wenn die Anzahl der Argumente bekannt ist.
v (vector) Die Argumente aus der Kommandozeile werden in Form eines Vektors argv[] übergeben. Die einzelnen Argumente sind also argv[0],argv[1],...argv[n]. Das letzte Argument (argv[n]) muss der NULL - Zeiger sein.
p (path) Die mit Namen angegebene Datei wird nicht nur im aktuellen Directory gesucht, sondern auch in den durch die Umgebungsvariable PATH bestimmten Directorys.
e (environment) Die Funktion erwartet die Environment - Liste als Vektor (envp[]) und benutzt nicht das aktuelle Environment.


Kommen wir zuerst zu einem Beispiel von execl . Schreiben sie zuerst folgendes Programm....

/*Download:exec1.c*/
#include <stdio.h> int main(int argc, char *argv[]) { int i=0; printf("%s\n",argv[0]); printf("Das neue Programm läuft und gibt aus : "); while(argv[++i] != NULL) printf("%s ",argv[i]); return 0; }

...speichern und compilieren es. Nennen wir es hellow. Dieses Programm wollen wir mit Hilfe der execl() - Funktion aufrufen mit weiteren Strings als Argumente. Hier der Programmaufruf .....

execl("hellow"," ","Hallo", "Welt", "wie", "geht's",NULL);  

Damit rufen sie das neue Programm hellow auf und übergeben dem Programm noch weitere Argumente. Dies entspricht das selbe wie wenn das Programm hellow in der Kommandozeile folgendermaßen aufrufen würden....

hellow Hallo Welt wie geht's  

In dem 2.String von execl() kann ich mir einen Eintrag sparen da dieser bei unserem neu Aufgerufenen Programm der Adresse von argv[0] entspicht und dieser steht für den Programmnamen. Mit dem folgenden Programm (execl) wird also das Programm hellow aufgerufen (vorausgesetzt es existiert) und hellow gibt anschließend aus...

Hallo Welt wie geht's  

Hier der Code zu execl.....

/*Download:exec2.c*/
#include <stdio.h> #include <unistd.h> int main(int argc, int *argv[]) { printf("%s wird ausgefuehrt...\n\n", argv[0]); printf("%s ruft auf ", argv[0]); execl("hellow","","Hallo", "Welt", "wie", "gehts",NULL); return 0; }

Bitte beachten sie wenn sie das Programm exec2 starten und das Programm hellow aufgerufen wird nicht mehr verfügbar ist. Das selbe wollen wir jetzt auch mit einem Vektor machen. Diese Programm demonstriert die Funktion execv()......

/*Download:exec2.c*/
#include <stdio.h> #include <unistd.h> int main(int argc, int *argv[]) { printf("%s wird ausgefuehrt...\n\n", argv[0]); printf("%s ruft auf ", argv[0]); execl("hellow","","Hallo", "Welt", "wie", "gehts",NULL); return 0; }

Diese Programm macht wieder das selbe wie unser Programm execl schon zuvor. Nur das wir die Kommandozeilenargumente als Vektor übergeben. Wir können aber auch die Argumente die wir beim Programmstart von execv eingeben an unser neues Programm übergeben......

/*Download:exec4.c*/
#include <stdio.h> #include <unistd.h> int main(int argc, int *argv[]) { printf("%s wird ausgefuehrt...\n\n", argv[0]); printf("%s ruft auf ", argv[0]); execv("hellow",argv); return 0; }

Bei diesen Beispielen dürfte Ihnen klar geworden sein wo die Unterschiede der Form der Argumentübergabe zwischen execl, execlp, execle UND execv, execvp, execve liegt...

execl,execlp,execle

Hier müssen die Kommandozeilenargumente des neu zu startenden Programms in Form einer Liste übergeben werden. Das Ende der Argumentliste wird mit einem NULL - Zeiger markiert. z.B...

execlp(programmname,"bla","blabla","blubb",NULL);  

execv,execvp,execve

Hier müssen wir die Kommandozeilenargumente des neu zu startenden Programms in Form eines Stringvektors (char *argv[]) übergeben. z.B.....

execv(programmname,argv);  

Die Benutzung der Funktionen execle und execve, also zusätzlich mit dem Buchstaben e, wird hauptsächlich dazu verwendet wenn das neu zu startende Programm das aktuelle Environment zu vererben. z.B. execle....

int main(int argc, char *argv[], char *envp[])
{
.......................
   execle(programmname,"Hallo","Welt",NULL,envp);
........................
}  

...oder bei execve...

execve(programmname,argv,envp);  

Bleibt uns nur noch eine kleine Anmerkung zu machen zu dem Buchstaben p, also execlp und execvp. Enthält der beim Aufruf angegebene Dateinamen einen Slash ('/' = Linux/Unix) oder einen Backslash ('\' = MS-Dos), so wird er als Pfadname interpretiert. Ansonsten wird in den PATH - Directorys nach einer Ausführbaren Datei mit diesem Namen gesucht und gestartet.

close-on-exec-Flag
Jetzt kommen wir zur Erklärung was das close-on-exec-Flag bewirkt wenn es gesetzt oder nicht gesetzt ist. Im Kapitel fcntl haben sie bereits gelernt wie man das close-on-exec-Flag verändern kann. Wenn das Flag nicht gesetzt ist (default-Einstellung) bleiben alle bereits geöffneten Dateien, beim neu durch einen exec-Aufruf gestarteten Programm, offen. Ist das Flag aber gesetzt, was sie mit der Funktion fcntl erreichen können werden die entsprechenden Filedeskriptoren beim exec-Aufruf geschlossen.

Die einzelnen exec - Funktionen haben wir bereits durchgenommen. Und was noch wichtig ist ändert sich bei einem Programm das sie mit exec Aufrufen nicht die PID da im Gegensatz zu fork nicht ein neuer Prozess gekreiert wird. Es werden nur die Segmente des akt. Prozesses durch den neuen überschrieben.

Die execl()-Funktion führt vor allem bei Programmierern, die die Funktion das erste Mal nutzen, zu Verwirrung. Dies liegt daran, Das das zweite an execl() übergebene Argument nicht das erste Kommandozeilenargument ist, das an das aufzurufende Programm (spezifiziert in path) übergeben wird. Vielmehr ist das zweite Argument der Name, unter dem der neue Prozess in der vom ps-Befehl erzeugten Prozessliste aufgeführt wird. Das erste Argument, das an das (in path spezifizierte) Programm übergeben wird, ist also tatsächlich das dritte Argument, das an execl() übergeben wird.

/*Download:exec5.c*/
#include <signal.h> #include <stdio.h> int main(int argc, char **argv) { pid_t kind; printf("Mein Programmname lautet : %s\n",*argv); printf("Mein PID lautet : %d\n",getpid()); printf("Ich werde jetzt durch 'ps -u' ersetzt!!!\n"); execl ("/bin/ps", "Prozesse", "-u", NULL); printf("Ich werde nie ausgeführt :(\n"); return 0; }

An diesem simplen Beispiel können sie sehen das der Prozess mit dem Namen *argv und der der Nummer PID durch den Prozess.....

execl ("/bin/ps", "Prozesse", "-u", NULL);  

...also den Aufruf ps -u ersetzt wird. 'Prozesse' ist der Eintrag des Namens der in der Prozessliste geführt wird. Und als Beweis das der Prozess komplett durch den neuen Ersetzt wird der Text 'Ich werde nie ausgeführt' auch wirklich nie ausgeführt. Sie können ja mal execl durch system("ps -u"); ersetzen. Damit wird nämlich die nächste Zeile wieder ausgeführt.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf