7 Changement de code d'un processus
La primitive
#include <unistd.h>
int execve (char *filename, char *argv[], char *envp[]) ;
transforme le processus appelant en un nouveau processus.
Attention, il n'y a pas création d'un nouveau processus, mais
recouvrement de l'ancien processus par le nouveau.
Le nouveau processus est construit à partir d'un fichier ordinaire
exécutable dont le nom est pointé par filename.
Le paramètre argv pointe sur un tableau de pointeurs de
chaînes de caractères terminé par un pointeur NULL. Ces
chaînes constituent la liste d'arguments du nouveau processus. Par
convention, argv[0] est toujours présent et doit être le nom
du programme à exécuter.
Le paramètre envp est aussi un pointeur sur un
tableau de pointeurs de chaînes de caractères terminé par un pointeur
NULL. Elles identifient les variables d'environnement qui
seront accessibles depuis le nouveau processus. Ces chaînes sont
construites suivant le format :
||<|nom de la variable||>|
=
||<|valeur de la variable||>|
Les descripteurs ouverts dans le processus appelant restent ouverts
dans le nouveau processus.
Quand le programme exécuté commence, il est appelé de la façon
suivante : (les paramètres argc, argv et
envp de main () sont optionnels)
main (int argc, char *argv[], char *envp[])
execve() retourne dans le processus appelant uniquement en cas
d'erreur et renvoie alors -1.
Exemple
% cat exec1.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
char *path = "./exec2" ;
char *argval[] = {"exec2", "foo", "bar", NULL} ;
int main (int argc, char *argv[], char *envp[])
{
pid_t pid ;
switch (retour = fork()) {
case -1 :
perror ("fork") ;
exit (1) ;
case 0 :
printf ("processus fils va executer exec\n") ;
execve (path, argval, envp) ;
perror ("execve") ;
exit (1) ;
default :
printf ("pere: a cree processus %d\n", retour) ;
wait(0) ;
printf ("pere: a recu terminaison fils\n") ;
}
}
% cat exec2.c
#include <stdio.h>
int main (int argc, char *argv[])
{
int i ;
printf ("execution de exec2\n") ;
printf ("exec2: %d arguments\n", argc) ;
for (i=0 ; i<argc ; i++)
printf ("exec2 argument %d: %s\n", i, argv[i]) ;
exit (0) ;
}
% ./exec1
processus fils va executer exec
pere: a cree processus 14625
execution de exec2
exec2: 3 arguments
exec2 argument 0: exec2
exec2 argument 0: foo
exec2 argument 0: bar
pere: a recu terminaison fils
D'autres primitives sont disponibles ; elles sont écrites à l'aide de
execve(). Il 'agit de execl(), execlp(), execle(),
execv(), et execvp() dont les prototypes sont les suivants :
#include <unistd.h>
int execl (const char *filename, const char *arg, ...) ;
int execlp (const char *cmdname, const char *arg, ...) ;
int execle (const char *filename char *arg , ..., char* const envp[]) ;
int execv (const char *filename, char *const argv[]) ;
int execvp (const char *cmdname, char *const argv[]) ;
Elles permettent de spécifier les arguments du nouveau processus sous
la forme d'une liste d'arguments (paramètres arg) et non d'un
tableau de chaînes de caractères (paramètres argv), et/ou de
rechercher le programme à exécuter parmi les chemins de recherches
(variable d'environnement $PATH, paramètres cmdname) et non
de spécifier complètement son chemin (paramètres filename), etc.