5.1 KiB
Cours 3
La création de processus via la commande fork
est intéressante mais son utilisation
est limitée. Le système fourni un compagnon à fork
l'appel système exec
. Son rôle est
de permettre à un processus de changer son code (recouvrir). On parle souvent des appels fork/exec
.
La famille exec
Il existe six primitives de préfixe commun exec
qui se différencient :
-
par la manière dont les arguments récupérés via l’argument
argv
sont transmis.-
soit directement sous forme d’un tableau ou vecteur (d’où le
v
) contenant les différents paramètres. Il s’agit des primitivesexecv
,execvp
etexecve
qui ont un nombre fixe de paramètres ; -
soit sous forme d’une liste (d’où le
l
)arg0, arg1, ..., argn, NULL
dans les primitivesexecl
,execlp
etexecle
qui ont ainsi un nombre variable de paramètres ;
-
-
par la manière dont le fichier à charger est recherché dans le système de fichiers :
- avec
execlp
etexecvp
le fichier est recherché dans les répertoires spécifiés via la variablePATH
de l’environnement (et dans l’ordre d’apparition) ; - avec les autres primitives, le fichier, s’il n’est pas désigné par une référence absolue, n’est recherché que relativement au répertoire de travail du processus appelant ;
- avec
-
par l’environnement conservé par le processus au cours du recouvrement :
- avec les primitives
execve
etexecle
un nouvel environnement transmis en paramètre se substitue à l’ancien ; - avec les autres primitives, l’environnement reste inchangé.
- avec les primitives
Le code de retour peut-être -1
en cas d'erreur.
Description
int execl (const char *reference, const char *arg0, ..., NULL);
Le fichier de reference
absolue ou relative (au répertoire de travail du processus) donnée est chargé et la fonction main
correspondante est appelée avec les paramètres de la liste constituée par les autres paramètres. Le paramètre arg0
est récupéré dans la fonction main
dans argv[0]
.
Par exemple
execl("/bin/ls", "ls", "-l", "/", NULL)
correspond à ls -l /
.
int execlp (const char *reference, const char *arg0, ..., NULL);
se comporte comme la précédente sauf que si la reference
est relative la recherche de la référence se fait dasn les répertoires spécifiés dans la varaible PATH
de votre environnement.
int execle (const char *reference, const char *arg0, ..., NULL, const char **arge);
même comportement que execl
mais le dernier paramètre pointe sur un environnement à substituer à l'ancien. Un environnement est constitué d'un ensemble de pointeurs sur des chaines de la forme nom=valeur (la fin de la liste est marquée par le pointeur NULL
).
Exemple
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main(int argc, char *argv[]) {
int ind;
char **ptr;
for (ind = 0; ind < argc; ind++) printf("%s\n", argv[ind]);
ptr = environ;
while (*ptr != NULL) printf("%s\n", *ptr++);
return EXIT_SUCCESS;
}
Dont voici une exécution :
bash-4.4$ ./recouvrante a s d f fg g=8
./recouvrante
a
s
d
f
fg
g=8
CONDA_SHLVL=1
CONDA_EXE=/anaconda3/bin/conda
LANG=fr_FR.UTF-8
XPC_FLAGS=0x0
DISPLAY=/private/tmp/com.apple.launchd.3687PRnHur/org.macosforge.xquartz:0
TERM_SESSION_ID=03974C81-0A61-46AD-80DE-7F8E93D00974
CONDA_PREFIX=/anaconda3
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.VXQ8jzyBiw/Listeners
USER=pvalarcher
PWD=/Users/pvalarcher/git/ASR31/notes_de_cours/Cours3
HOME=/Users/pvalarcher
CONDA_PYTHON_EXE=/anaconda3/bin/python
TERM_PROGRAM=Apple_Terminal
TERM_PROGRAM_VERSION=421.2
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.MVmgyBLeD8/Render
TMPDIR=/var/folders/fz/3908mpd559x0cywbp_kvkhx00000gn/T/
CONDA_PROMPT_MODIFIER=
XPC_SERVICE_NAME=0
TERM=xterm-256color
SHELL=/bin/bash
SECURITYSESSIONID=186aa
SHLVL=2
LOGNAME=pvalarcher
PATH=/anaconda3/bin:/Library/Frameworks/Python.framework/Versions/3.7/bin:/Users/pvalarcher/anaconda/bin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/opt/X11/bin
CONDA_DEFAULT_ENV=base
_=./recouvrante
OLDPWD=/Users/pvalarcher/git/ASR31/notes_de_cours
bash-4.4$
int execv(const char *reference, const char *argv[]);
charge reference
et appelle main
avec les paramètres argc
et argv
.
Exemple
#include <stdio.h>
#include <unistd.h>
#define NMAX 5
main() {
char *argv[NMAX]; /* NMAX > 3 */
argv[0] = "ls"; argv[1] = "-l"; argv[2]="/"; argv[3]=NULL;
execv("/bin/ls", argv);
perror("execv");
}
Exercice
Montrer que argc
contient bien la bonne valeur.
int execvp(const char *reference, const char *argv[]);
comme execv
mais avec recherche dans le cas ou reference
est relative dans PATH
.
int execvp(const char *reference, const char *argv[], const char **arge);
comme execv
mais avec installation d'un nouvel environnement.
On peut modifier des attributs du processus après recouvrement.