ASR31-valarche-2021/ASR31-4-Exec.md

5.1 KiB
Raw Blame History

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 largument argv sont transmis.

    • soit directement sous forme dun tableau ou vecteur (doù le v) contenant les différents paramètres. Il sagit des primitives execv, execvp et execve qui ont un nombre fixe de paramètres ;

    • soit sous forme dune liste (doù 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 lenvironnement (et dans lordre dapparition) ;
    • avec les autres primitives, le fichier, sil nest pas désigné par une référence absolue, nest recherché que relativement au répertoire de travail du processus appelant ;
  • par lenvironnement conservé par le processus au cours du recouvrement :

    • avec les primitives execve et execle un nouvel environnement transmis en paramètre se substitue à lancien ;
    • avec les autres primitives, lenvironnement reste inchangé.

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 dans les répertoires spécifiés dans la variable 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.