mise à jour
This commit is contained in:
parent
a1b9d70868
commit
c2b219f7a0
160
ASR31-Cours4.md
Normal file
160
ASR31-Cours4.md
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# 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 <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 :
|
||||||
|
|
||||||
|
```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 <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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```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.
|
||||||
|
|
||||||
|
|
23
Exemples/04-Exec/apresExec.c
Normal file
23
Exemples/04-Exec/apresExec.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
char tabRef[1000];
|
||||||
|
int nbLu;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Caractéristiques après recouvrement\n");
|
||||||
|
printf(" => Identité du processus:%d\n",getpid());
|
||||||
|
printf(" => Identité du processus père:%d\n",getppid());
|
||||||
|
printf(" => Propriétaire réel : %d\n", getuid());
|
||||||
|
printf(" => Propriétaire effectif : %d\n", geteuid());
|
||||||
|
printf(" => Répertoire de travail:%s\n",getcwd(tabRef,1000));
|
||||||
|
|
||||||
|
if ((nbLu = read(STDIN_FILENO,&c,1)) == -1)
|
||||||
|
perror(" read");
|
||||||
|
else
|
||||||
|
printf(" Valeur du read : %d\n", nbLu);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
22
Exemples/04-Exec/avantExec.c
Normal file
22
Exemples/04-Exec/avantExec.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
char tabRef[1000];
|
||||||
|
|
||||||
|
main() {
|
||||||
|
printf("Caractéristiques avant recouvrement\n");
|
||||||
|
printf(" Identité du processus : %d\n", getpid());
|
||||||
|
printf(" Identité du processus père:%d\n",getppid());
|
||||||
|
printf(" Propriétaire réel : %d\n", getuid());
|
||||||
|
printf(" Propriétaire effectif : %d\n", geteuid());
|
||||||
|
printf(" Répertoire de travail:%s\n",getcwd(tabRef,1000));
|
||||||
|
/* demande de fermeture automatique de l’entrée standard au recouvrement */
|
||||||
|
|
||||||
|
fcntl(STDIN_FILENO, F_SETFD, fcntl(STDIN_FILENO,F_GETFD,0)|FD_CLOEXEC);
|
||||||
|
|
||||||
|
execl("apresExec", "apresExec", NULL);
|
||||||
|
|
||||||
|
perror("execl");
|
||||||
|
|
||||||
|
}
|
18
Exemples/04-Exec/recouvrante.c
Normal file
18
Exemples/04-Exec/recouvrante.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#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;
|
||||||
|
}
|
16
Exemples/04-Exec/recouvre1.c
Normal file
16
Exemples/04-Exec/recouvre1.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* binaire : recouvre1 */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
char *envp[3];
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
envp[0] = "X=AAAAA"; envp[1] = "Y=BBB"; envp[2] = NULL;
|
||||||
|
|
||||||
|
execl( "recouvrante", "recouvrante", "/tmp/ddd", NULL, envp);
|
||||||
|
|
||||||
|
|
||||||
|
perror("execl");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
15
Exemples/04-Exec/recouvre2.c
Normal file
15
Exemples/04-Exec/recouvre2.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* binaire : recouvre2 */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
char *envp[3];
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
envp[0] = "X=AAAAA"; envp[1] = "Y=BBB"; envp[2] = NULL;
|
||||||
|
|
||||||
|
execle( "recouvrante", "recouvrante", "/tmp/ddd", NULL, envp);
|
||||||
|
|
||||||
|
perror("execle");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
13
Exemples/04-Exec/recouvrement_ls.c
Normal file
13
Exemples/04-Exec/recouvrement_ls.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#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");
|
||||||
|
}
|
99
Exemples/04-Exec/shellex.c
Normal file
99
Exemples/04-Exec/shellex.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#define MAXARGS 128
|
||||||
|
#define MAXLINE 80
|
||||||
|
#define FOREVER while(1)
|
||||||
|
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
void eval(char *cmdline);
|
||||||
|
int parseline(char *buf, char **argv);
|
||||||
|
int builtin_cmd(char **argv);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char cmdline[MAXLINE];
|
||||||
|
|
||||||
|
FOREVER {
|
||||||
|
printf("> ");
|
||||||
|
fgets(cmdline, MAXLINE, stdin);
|
||||||
|
if (feof(stdin)) exit(0);
|
||||||
|
|
||||||
|
eval(cmdline);
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eval(char *cmdline) {
|
||||||
|
char *argv[MAXARGS];
|
||||||
|
char buf[MAXLINE];
|
||||||
|
int bg;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
strcpy(buf, cmdline);
|
||||||
|
bg = parseline(buf, argv);
|
||||||
|
if (argv[0] == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!builtin_cmd(argv)) {
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
if (execvp(argv[0], argv) < 0) {
|
||||||
|
printf("%s: cette commande n'existe pas.\n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bg) {
|
||||||
|
int status;
|
||||||
|
if (waitpid(pid, &status, 0) < 0) {
|
||||||
|
perror("waitfg: waitpid error"); exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%d %s", pid, cmdline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int builtin_cmd(char **argv) {
|
||||||
|
if (!strcmp(argv[0], "quit"))
|
||||||
|
exit(0);
|
||||||
|
if (!strcmp(argv[0], "&"))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseline(char *buf, char **argv) {
|
||||||
|
char *delim;
|
||||||
|
int argc;
|
||||||
|
int bg;
|
||||||
|
|
||||||
|
buf[strlen(buf)-1] = ' ';
|
||||||
|
while (*buf && (*buf == ' ')) {
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc = 0;
|
||||||
|
while ((delim = strchr(buf, ' '))) {
|
||||||
|
argv[argc++] = buf;
|
||||||
|
*delim = '\0';
|
||||||
|
buf = delim+1;
|
||||||
|
while (*buf && (*buf == ' ')) buf++;
|
||||||
|
}
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
if (argc == 0) return 1;
|
||||||
|
|
||||||
|
if ((bg = (*argv[argc-1] == '&')) != 0) {
|
||||||
|
argv[--argc] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bg;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user