# 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 primitives ```execv```, ```execvp``` et ```execve``` qui ont un nombre fixe de paramètres ; - soit sous forme d’une liste (d’où le ```l```) ```arg0, arg1, ..., argn, NULL``` dans les primitives ```execl```, ```execlp``` et ```execle``` 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``` et ```execvp``` le fichier est recherché dans les répertoires spécifiés via la variable ```PATH``` 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 ; - par l’environnement conservé par le processus au cours du recouvrement : - avec les primitives ```execve``` et ```execle``` un nouvel environnement transmis en paramètre se substitue à l’ancien ; - avec les autres primitives, l’environnement reste inchangé. Le code de retour peut-être $-1$ en cas d'erreur. ### Description ```c 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 ```c execl("/bin/ls", "ls", "-l", "/", NULL) ``` correspond à ```ls -l /```. ```c 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. ```c 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 ```c #include #include 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 : ```sh 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$ ``` ```c int execv(const char *reference, const char *argv[]); ``` charge ```reference``` et appelle ```main``` avec les paramètres ```argc``` et ```argv```. #### Exemple ```c #include #include #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. ```c int execvp(const char *reference, const char *argv[]); ``` comme ```execv``` mais avec recherche dans le cas ou ```reference``` est relative dans ```PATH```. ```c 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.