Examen systèmes d'exploitation Examen SE - processus - Le shell et les scripts
Objectifs : - Les processus dans un SE.
- La communication par signaux et par tubes.
- Le shell et les scripts.
- Programmer sous un SE.
NB : Les valeurs de retour des primitives ne sont pas syst´ematiquement test´ees dans les programmes de l’´enonc´e. On supposera donc que les primitives ne renvoient jamais un code d’erreur.
Les processus
Exercice 1.
1. Combien de processus engendre l’´evaluation de la commande C
fork() && ( fork() || fork() ) ;
2. Dessiner l’arbre g´en´ealogique des processus engendr´ees par cette ligne.
Exercice 2. Consid´erer le programme suivant :
--------------------------------------------
forkpause.c
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <unistd.h>
4 : #include <signal.h>
5 :
6 : void interruption(int signum)
7 : {
8 : if (signum == SIGINT)
9 : printf("UN\n");
10 : }
11 :
12 : int main(void)
13 : {
14 : int pid;
15 :
16 : signal(SIGINT, &interruption);
17 : signal(SIGALRM, &interruption);
18 : pid = fork();
19 : srand(pid);
20 : if (!pid)
21 : {
22 : sleep(rand() % 2);
23 : printf("DEUX\n");
24 : kill(getppid(), SIGINT);
25 : } else
26 : {
27 : alarm(5);
28 : sleep(rand() % 2);
29 : printf("TROIS\n");
30 : pause();
31 : }
32 : exit(EXIT_SUCCESS);
33 : }
--------------------------------------------
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <unistd.h>
4 : #include <signal.h>
5 :
6 : void interruption(int signum)
7 : {
8 : if (signum == SIGINT)
9 : printf("UN\n");
10 : }
11 :
12 : int main(void)
13 : {
14 : int pid;
15 :
16 : signal(SIGINT, &interruption);
17 : signal(SIGALRM, &interruption);
18 : pid = fork();
19 : srand(pid);
20 : if (!pid)
21 : {
22 : sleep(rand() % 2);
23 : printf("DEUX\n");
24 : kill(getppid(), SIGINT);
25 : } else
26 : {
27 : alarm(5);
28 : sleep(rand() % 2);
29 : printf("TROIS\n");
30 : pause();
31 : }
32 : exit(EXIT_SUCCESS);
33 : }
--------------------------------------------
1. R´epondre aux questions suivants, en expliquant votre r´eponse.
– Que peut se passer si l’on supprime la ligne 30 ?
– Que peut se passer si l’on supprime la ligne 27 ?
– Que se passe-t-il si on ´echange l’ordre des lignes 18-19 ?
2. Donner les diff´erents affichages pouvant ˆetre produits par ce programme.
La communication par signaux
--------------------------------------------
signaux.c
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <unistd.h>
4 : #include <signal.h>
5 :
6 : sigset_t ens_vide, ens_tstp;
7 : struct sigaction action;
8 :
9 : void handler(int sig)
10 : {
11 : switch (sig)
12 : {
13 : case SIGQUIT:
14 : sigprocmask(SIG_SETMASK, &ens_vide, NULL);
15 : sigprocmask(SIG_SETMASK, &ens_tstp, NULL);
16 : sigaction(SIGINT, &action, NULL);
17 : break;
18 : case SIGINT:
19 : printf("A+\n");
20 : exit(0);
21 : break;
22 : case SIGTSTP:
23 : printf("Bonjour\n");
24 : break;
25 : default:
26 : break;
27 : }
28 : return;
29 : }
30 :
31 : int main(void)
32 : {
33 : action.sa_handler = handler;
34 : sigemptyset(&action.sa_mask);
35 :
36 : sigemptyset(&ens_vide);
37 : sigemptyset(&ens_tstp);
38 : sigaddset(&ens_tstp, SIGTSTP);
39 : sigprocmask(SIG_SETMASK, &ens_tstp, NULL);
40 :
41 : sigaction(SIGTSTP, &action, NULL);
42 : sigaction(SIGQUIT, &action, NULL);
43 :
44 : for (;;);
45 :
46 : exit(0);
47 : }
--------------------------------------------
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <unistd.h>
4 : #include <signal.h>
5 :
6 : sigset_t ens_vide, ens_tstp;
7 : struct sigaction action;
8 :
9 : void handler(int sig)
10 : {
11 : switch (sig)
12 : {
13 : case SIGQUIT:
14 : sigprocmask(SIG_SETMASK, &ens_vide, NULL);
15 : sigprocmask(SIG_SETMASK, &ens_tstp, NULL);
16 : sigaction(SIGINT, &action, NULL);
17 : break;
18 : case SIGINT:
19 : printf("A+\n");
20 : exit(0);
21 : break;
22 : case SIGTSTP:
23 : printf("Bonjour\n");
24 : break;
25 : default:
26 : break;
27 : }
28 : return;
29 : }
30 :
31 : int main(void)
32 : {
33 : action.sa_handler = handler;
34 : sigemptyset(&action.sa_mask);
35 :
36 : sigemptyset(&ens_vide);
37 : sigemptyset(&ens_tstp);
38 : sigaddset(&ens_tstp, SIGTSTP);
39 : sigprocmask(SIG_SETMASK, &ens_tstp, NULL);
40 :
41 : sigaction(SIGTSTP, &action, NULL);
42 : sigaction(SIGQUIT, &action, NULL);
43 :
44 : for (;;);
45 :
46 : exit(0);
47 : }
--------------------------------------------
On rappelle que la frappe de CTRL-C envoie le signal SIGINT au processus qui se trouve en avant-plan. De mˆeme pour CTRL-\ et SIGQUIT (on suppose que l’on se trouve pas sur une machine Sun) et CTRL-Z et SIGTSTP.
Exercice 3.
Commenter, ligne par ligne, le programme signaux.c, en donnant assez d’explications.
Exercice 4.
Dire ce qui est affich´e `a l’´ecran si – pendant l’ex´ecution en avant-plan du programme ci dessus – l’on tape :
1. CTRL-Z, CTRL-C,
2. CTRL-\, CTRL-C,
3. CTRL-Z, CTRL-\, CTRL-C,
4. CTRL-\, CTRL-Z, CTRL-C,
5. CTRL-\, CTRL-Z, CTRL-\, CTRL-C,
6. CTRL-Z, CTRL-Z, CTRL-\, CTRL-C,
La communication par tubes
Consid´erer le programme suivant :
-------------------------------------------- tubes.c
1:#include<stdlib.h>
2:#include<unistd.h>
3:#include<fcntl.h>
4:#include<sys/stat.h>
5:
6:char*nom_pf="tube_pf";
7:chartampon[100];
8:intno_lu;
9:
10:voidpere(d_lecture)
11:{
12:intd_ecriture;
13:
14:while((no_lu=read(d_lecture,tampon,sizeof(tampon)))>0)
15:{
16:d_ecriture=open(nom_pf,O_WRONLY);
17:write(d_ecriture,tampon,no_lu);
18:close(d_ecriture);
19:}
20:exit(0);
21:}
22:
23:voidfils(d_ecriture)
24:{
25:char*message="abcdefghilmno\n";
26:intd_lecture=open(nom_pf,O_RDONLY);
27:
28:do
29:{
30:if(*message==0)
31:break;
32:write(d_ecriture,message++,sizeof(char));
33:no_lu=read(d_lecture,tampon,sizeof(tampon));
34:write(1,tampon,no_lu);
35:}
36:while(no_lu>0);
37:
38:exit(0);
39:}
40:
41:intmain(void)
42:{
43:intfp[2];
44:
45:unlink(nom_pf);
46:mkfifo(nom_pf,0600);
47:pipe(fp);
48:
49:if(fork())
50:pere(fp[0]);
51:else
52:fils(fp[1]);
53:
54:exit(0);
55:}
--------------------------------------------
1:#include<stdlib.h>
2:#include<unistd.h>
3:#include<fcntl.h>
4:#include<sys/stat.h>
5:
6:char*nom_pf="tube_pf";
7:chartampon[100];
8:intno_lu;
9:
10:voidpere(d_lecture)
11:{
12:intd_ecriture;
13:
14:while((no_lu=read(d_lecture,tampon,sizeof(tampon)))>0)
15:{
16:d_ecriture=open(nom_pf,O_WRONLY);
17:write(d_ecriture,tampon,no_lu);
18:close(d_ecriture);
19:}
20:exit(0);
21:}
22:
23:voidfils(d_ecriture)
24:{
25:char*message="abcdefghilmno\n";
26:intd_lecture=open(nom_pf,O_RDONLY);
27:
28:do
29:{
30:if(*message==0)
31:break;
32:write(d_ecriture,message++,sizeof(char));
33:no_lu=read(d_lecture,tampon,sizeof(tampon));
34:write(1,tampon,no_lu);
35:}
36:while(no_lu>0);
37:
38:exit(0);
39:}
40:
41:intmain(void)
42:{
43:intfp[2];
44:
45:unlink(nom_pf);
46:mkfifo(nom_pf,0600);
47:pipe(fp);
48:
49:if(fork())
50:pere(fp[0]);
51:else
52:fils(fp[1]);
53:
54:exit(0);
55:}
--------------------------------------------
Exercice 5.
Donner un aper¸cu sur le programme, en expliquant de fa¸con succincte ce qui devrait faire.
Exercice 6.
Dans le programme on y trouve des erreurs de traitement des tubes : une premi`ere erreur regarde le traitement des tubes nomm´ees, une deuxi`eme erreur regarde le traitement des tubes anonymes.
Trouver ces deux erreurs, pour chacune erreur expliquer la raison pour lequel il s’agit d’une erreur et le corriger.
Le shell et les scripts
Exercice 7. Consid´erer le script pluff.sh.
-------------------------------------------- pluff.sh
1 : #!/bin/bash
2 :
3 : if [ "$1" -eq 0 ]
4 : then
5 : echo $1
6 : else
7 : ARG=‘expr $1 - 1‘
8 : $0 $ARG $2 | $2
9 : fi
--------------------------------------------
1 : #!/bin/bash
2 :
3 : if [ "$1" -eq 0 ]
4 : then
5 : echo $1
6 : else
7 : ARG=‘expr $1 - 1‘
8 : $0 $ARG $2 | $2
9 : fi
--------------------------------------------
Écrire un programme en langage C ´equivalent au script pluff.sh. On utilisera les primitives pipe, dup, execlp.
Exercice 8. Consid´erer le programme succ.c :
--------------------------------------------
succ.c
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 :
4 : int main(void)
5 : {
6 : int i;
7 :
8 : scanf("%d", &i);
9 : fprintf(stderr, "%d\n", 1);
10 : printf("%d\n", ++i);
11 : exit(0);
12 : } --------------------------------------------
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 :
4 : int main(void)
5 : {
6 : int i;
7 :
8 : scanf("%d", &i);
9 : fprintf(stderr, "%d\n", 1);
10 : printf("%d\n", ++i);
11 : exit(0);
12 : } --------------------------------------------
On supposera qu’un ex´ecutable succ (correspondant au programme succ.c) et le fichier pluff.sh se trouvent dans un des r´epertoires de la variable d’environnement PATH.
1. Dire ce qui est affich´e `a l’´ecran par la commande
$ pluff.sh 3 succ
2. Combien de processus nomm´es succ sont engendr´es par la mˆeme commande ? Combien de processus nomm´es
succ sont engendr´es par la commande
$ pluff.sh n succ
ouù n est un nombre entier positif.
3. Peut-on remplacer les lignes 9-10 du programme succ.c par la ligne
printf("%d\n%d\n",1,++i);
?
Expliquer votre r´eponse.
Un peu de programmation
Exercice 9.
Donner le sch´ema d’un programme serveur. Le serveur ´ecoute sur une tube nomm´e, et, chaque fois qu’il recoit une requˆete de connexion par un processus client, il cr´ee un fils qui s’occupe de traiter la connexion `a l’aide d’une nouvelle couple de tubes nomm´ees (la communication est bidirectionnelle) d´edi´ee `a cette connexion. Le serveur ne s’arrˆete jamais.
On peut faire l’hypoth`ese qu’un client demande une connexion en ´ecrivant son PID dans le tube du serveur. On d´etaillera seulement la gestion des tubes par le fils, et non le traitement de la connexion.
Article plus récent Article plus ancien