Vous êtes sur la page 1sur 15

Prof. C.

EL AMRANI Programmation systme sous UNIX


Chapitre 1.

1. Les appels systme pour les processus

1.1. Les processus
Un processus est un programme qui sexcute et qui possde son compteur ordinal, ses
registres et ses variables. Conceptuellement, chaque processus a son propre processeur
virtuel. En ralit, le vrai processeur commute entre plusieurs processus. Cette commutation
rapide sappelle multiprogrammation.
1.1.1. Hirarchie entre les processus
Les systmes dexploitation qui font appel au concept de processus doivent permettre de
crer les processus requis. Dans la plupart des systmes, il faut pouvoir crer et dtruire
dynamiquement les processus. En Unix, un processus particulier init est lanc au dmarrage
de la machine. Il cre un processus par terminal, lorsque la connexion est valide, il lance un
nouveau processus charg de lire et dinterprter les commandes de lutilisateur (Shell).
Chacune de ces commandes peut elle-mme crer un nouveau processus et ainsi de suite.
Notez quun processus na quun seul pre mais peut avoir plusieurs fils. Tous les processus
du systme font donc partie dun seul arbre dont la racine est init.
1.1.2. Les diffrents tats dun processus
Les processus, bien qutant des entits indpendantes, doivent parfois interagir avec
dautres processus. Les rsultats dun processus peuvent, par exemple, tre les donnes dun
autre.
Exemple :
ls l | more

Les tats possibles dun processus sont les suivants :
1. Elu : en cours dexcution. Un processus lu peut tre arrt, mme sil peut poursuivre
son excution, si le SE dcide dallouer le processeur un autre processus
2. Bloqu : attend un vnement extrieur pour pouvoir continuer, par exemple une
ressource, lorsque la ressource est disponible, il passe ltat prt
3. prt : suspendu provisoirement pour permettre lexcution dun autre processus
Quatre transitions peuvent avoir lieu entre ces diffrents tats :









Elu
Bloqu Prt
2 1
3
4
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
2
1 : Le processus se bloque en attente de donnes
2 : Lordonnanceur choisit un autre processus
3 : Lordonnanceur choisit ce processus
4 : Les donnes deviennent disponibles

Le modle des processus permet de mieux comprendre ce qui se passe lintrieur du
systme. Une partie des processus excutent les programmes qui traitent les commandes
tapes par les utilisateurs. Les autres processus font partie du systme et grent les tches
telles que les requtes au gestionnaire de fichiers ou les oprations sur les disques. Ces
processus se bloquent lorsquils attendent un vnement.
La couche la plus basse dun SE est lordonnanceur (scheduler). Il est surmont par une
multitude de processus. La gestion des interruptions, la suspension et la relance des
processus sont reportes dans lordonnanceur.









1.1.3. Les processus en UNIX
La commande ps liste, avec plus ou moins de dtails, tous les processus ou seulement ceux
de lutilisateur, suivant diffrentes options. Ainsi :
ps fH uetudiant1
prsente les champs :

UID Nom du propritaire du processus
PID Numro du processus
PPID Numro du processus pre
STIME Heure de lancement du processus
TTY Le terminal ou la fentre du processus
CMD La commande qui a permis de lancer le processus
ps e : affiche tous les processus de tous les utilisateurs
Exemple :
ps fH uetudiant

UID PID PPID C STIME TTY TIME CMD
etudiant10 533 1 0 09:44 pts/0 00:00:03 xemacs
etudiant10 531 1 0 09:44 pts/0 00:00:01 konsole
etudiant10 535 531 0 09:44 pts/1 00:00:00 /bin/bash
etudiant10

602 535 0 09:50 pts/1 00:00:00 more essai1.dat

0

1



n-2

n-1

Ordonnanceur (scheduler)

Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
3
La hirarchie des processus est reprsente par larbre suivante :













Le processus 1 (init) est le pre des processus 533 et 531 correspondant des fentres X
Window.
1.2. Les appels systme (processus)
1.2.1. Caractristiques dun processus

Les appels systmes :

int getpid () fournit le numro du processus en cours dexcution
int getppid () fournit le numro du pre du processus

#include <stdio.h>
#include <unistd.h>
main()
{
printf("pid: %d, ppid: %d\n",getpid(), getppid());
}

Un utilisateur non propritaire dun programme excutable peut obtenir, le temps de
lexcution du programme, lidentit du propritaire du programme de faon bnficier des
droits daccs du propritaire. Pour cela, le propritaire doit positionner un droit s au lieu du
x pour les droits daccs du programme
Lors de lexcution, il y a un utilisateur rel (uid) et un utilisateur effectif (euid). La mme
possibilit existe pour les groupes, un utilisateur peut prendre le groupe du propritaire du
fichier, le temps de lexcution du programme. Il y a donc un groupe rel (gid) et un groupe
effectif (egid).
Les appels systmes correspondant sont :

int getuid () fournit le numro du propritaire rel
int geteuid () fournit le numro du propritaire effectif
int getgid () fournit le numro du groupe rel
int getegid () fournit le numro du groupe effectif

Exemple ;
1
533 (xemacs) 531 (konsole)
535 (/bin/bash)
602 (more)
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
4
Lexcutable /usr/bin/passwd, dont root est propritaire, a un droit daccs s (-r-s--x--x).
Les utilisateurs de /usr/bin/passwd acquirent, le temps de lexcution du programme, les
droits daccs root sur /etc/passwd (-rw-r--r--).
1.2.2. Lappel systme pipe
Un fichier est constitu de plusieurs descripteurs. Un descripteur est un entier compris entre
0 et 255 pour Linux. 0, 1 et 2 sont rservs pour lentre, la sortie standard la sortie en cas
derreurs. (3 pour la sortie dun tube, 4 pour lentre dun tube)





Un tube de communication est un tuyau dans lequel un processus crit des donnes quun
autre processus peut lire.
Lappel systme pipe () cre un tube anonyme et fournit un double descripteurs utilis pour
lire ou crire dans le tube :
int pipe (int descripteur [2]) dclar dans <unistd.h>
Le tube est entirement sous le contrle du noyau et rside en mmoire. Le processus reoit
les deux descripteurs correspondant lentre et la sortie du tube. Le descripteur dindice 0
est la sortie du tube, il est ouvert en lecture seule. Le descripteur 1 est lentre, ouverte en
criture seule.
En effet, les tubes sont des systmes de communication unidirectionnels.











Tube de communication
#include<stdio.h>
#include<unistd.h> // pour certaines distributions de Linux, exit() est dfinit dans
main() // <stdlib.h>, il faudrait donc rajouter cette bibliothque pour que
{ // a fonctionne
int tube[2];
unsigned char buffer[256];
int i;

printf("creation du tube\n");
if(pipe(tube)!=0)
{
perror("pipe");
exit(1);
NOYAU
Ente Sortie
Processus
read() write()

Processus
0
2
tube[1] tube[0]
1
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
5
}
for (i=0;i<256;i++) buffer[i]=i;
printf("ecriture dans le tube\n");
if(write(tube[1],buffer,256)!=256)
{
perror("ecriture");
exit(1);
}
printf("lecture depuis le tube\n");
if(read(tube[0],buffer,256)!=256)
{
perror("lecture");
exit(1);
}
printf("tube[0]: %d\n",tube[0]); /* =3 (descripteur 3 du processus), lecture, sortie du tube
*/
printf("tube[1]: %d\n",tube[1]); /* =4 (descripteur 4 du processus), criture, entre du tube
*/ }
les descripteurs pointent vers les inodes du tube.
La cration dun tube pour un seul processus ne prsente aucun intrt. On utilise ce
mcanisme pour faire communiquer deux processus (ou plus), en invoquant les appels
systmes exec et fork.












Tube du pre vers le fils
1.2.3. Lappel systme execve et les fonctions de la famille exec
Lappel systme execve() excute un programme excutable ou un script shell. La syntaxe
est la suivante :
int execve (const char* filename, char* const argv[ ], char* const envp[ ]) ;

filename Nom ou chemin du fichier excuter
argv Tableau contenant les arguments du programme
envp Tableau contenant les variables denvironnement

Rappel :
Rappel sur main :
main (int argc, char* argv[ ], char* envp [ ])

0
1
2
3 tube[0]
4
tube[1]
Pre
Fils
tube[1] tube[0]
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
6
le pre
argc Nombre de paramtres sur la ligne de commande (c : counter)
argv Pointeur vers un tableau de pointeurs qui dsignent des donnes de type char
(v : vector)
envp Pointeur vers un tableau de pointeurs qui dsignent les variables
denvironnement (p : pointer)
Rappel sur un pointeur avec indice :
Soit: char *pt;
On a: pt[ i ] = *(pt+i) avec pt=&t[k] par exemple
Et donc pt[ i ] est de type char

Il existe 5 variantes de execve ()
Les paramtres sont donnes dans une liste (do l), termine par NULL :

int execl (const char* filename, char* const arg, ) ;

int execlp (const char* filename, char* const argv, ) ;
p indique que lexcutable doit tre cherch en utilisant la variable PATH

int execle (const char* filename, char* const argv, , char* const envp[ ]) ;
e indique que le tableau des variables denvironnement suit la liste des paramtres

int execv (const char* filename, char* const argv[ ]) ;
v indique que les paramtres sont dans un tableau (v : vector)
int execvp (const char* filename, char* const argv[ ]) ;

Exemple :
/* execls.c */
#include<stdio.h>
#include<unistd.h>
main()
{
execlp("ls","ls",NULL);
perror("erreur sur execlp");
}
Lexcution donne le listing des fichiers/rpertoires du rpertoire courant.
1.2.4. Lappel systme fork de cration de processus
Lappel systme fork () (de <unistd.h>) cre un processus fils qui diffre de son pre
uniquement par son numro de PID et PPID. Fork() fournit 0 pour le fils. La syntaxe est :
pid_t fork(void)








fork()
exit(0)
le fils
=0
!=0
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
7
fork1.c
#include<stdio.h>
#include<unistd.h>
main()
{
if (fork()==0)
{
//sleep (5) ; /* attendre 5 secondes */
printf ("processus fils: PID = %d , PPID = %d\n",getpid(), getppid());
exit(0);
}
printf("processus pere: PID = %d , PPID = %d\n",getpid(),getppid());
}
Excution :
processus fils: PID = 2024 , PPID = 2023
processus pere: PID = 2023 , PPID = 1924

Rq : si linstruction sleep(5) est prise en compte :

processus pere: PID = 2033 , PPID = 1924
autres commandes
processus fils: PID = 2034 , PPID = 1 le processus fils est adopt par le processus
initial init de PID = 1, car le pre se termine
avant le fils
1.2.5. Autres appels systme sur les processus
lappel systme wait bloque un processus en attente de la fin de lexcution dun fils quil a
cr. La syntaxe est :
pid_t wait (int * status) ;
la fonction retourne le PID du fils qui vient de se terminer. Status, sil est non NULL, reoit
des informations sur la faon dont sest termine le processus (valeur du exit du fils). Il
existe aussi lappel systme : waitpid qui permet dattendre la fin dun fils particulier.

Lappel systme _exit termine le processus courant. Sil reste des fils non termins, ceux-ci
reoivent le processus 1 pour pre. Sa syntaxe :
void _exit (int status) ;
La fonction exit ralise lappel systme _exit :
void exit (int status) ;

La fonction sleep () suspend un processus pendant le nombre de secondes indiqu en
paramtre. Sa syntaxe :
unsigned int sleep (unsigned int seconds) ;
Si la fonction est interrompue (par un signal) elle fournit le nombre de secondes restant
avant la fin programme, 0 sinon.
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
8
le pre
wait attendre la fin du 1
er
fils
wait attendre la fin du 2
me
fils
1.3. Utilisation de fork, exec, pipe, dup2
1.3.1. Excution de deux processus squentiels indpendants
Pour excuter les deux commandes : pwd et ls -li linterprteur de commandes (bash) doit
crer un processus, lui faire excuter pwd et attendre la fin du processus fils. Il peut alors
crer un nouveau processus et lui faire excuter la commande ls -l






















Le programme en C fork1.c est le suivant :

#include<stdio.h>
#include<unistd.h>
#include<wait.h>
main()
{
if(fork()==0)
{
printf("execution de pwd\n");
execlp("pwd","pwd",NULL);
perror ("Pb pwd");
exit(1);
}
wait(0);
if(fork()==0)
{
printf("execution de ls -l\n");
execlp("ls","ls","-l",NULL);
fork()
exit(1) en cas derreur
Le 1 fils excute
pwd et se termine
=0
!=0
fork()
exit(1) en cas derreur
Le 2 fils excute ls -l et
se termine
=0
!=0
Cration de 2 processus squentiels indpendants
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
9
perror("Pb ls -li");
exit(1);
}
wait(0);
}
Excution :
$ ./fork2
$ execution de pwd
$ /home/compte6/syst
$ execution de ls -l
total 88
62662 -rwxr--r-- 1 compte6 groupe2 14 avr 11 15:33 c
62658 -rwxr-xr-x 1 compte6 groupe2 11795 avr 11 16:52 execls

1.3.2. Redirection des entres et des sorties sur un fichier

Filtres en C
Un filtre Unix lit les donnes sur son entre standard, les modifie et les envoie sur sa sortie
standard. Les entres et sorties standards peuvent tre rediriges vers un fichier ou un tube.
Les messages derreurs doivent tre crits sur la sortie derreur (N 2, stderr au niveau de la
bibliothque standard, pour les filtres en C)




Exemples :

soit le filtre majuscul :
majuscul.c
#include<stdio.h>
#include<ctype.h> /* toupper */
main()
{
int c;
while((c=getchar())!=EOF)
putchar(toupper(c));
}
excution :
(soit un fichier de texte essai1.txt : bonjour)
$ ./majuscul < essai1.txt (dans essai1.txt : bonjour)
BONJOUR

soit le filtre par :
par.c
#include<stdio.h>
#include<stdlib.h>
main(int argc, char* argv[])
2
0

filtre
1
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
10
{
int largeur=10; /*par defaut*/
int n=0; /*nombre de caracteres*/
char c;

if (argc==2)largeur= atoi(argv[1]);
while((c=getchar()) != EOF)
{
if(c=='\n')c=' ';
putchar(c);
if(++n >= largeur)
{
putchar('\n');
n=0;
}
}
putchar('\n');
}
excution :
(soit un fichier de texte essai2.txt : bonjour monsieur)
$ ./par 4 < essai2.txt
bonj
our
mons
ieur


Voici un programme en shell bash qui excute ces deux programmes, et communique les
informations de sortie du premier, en entre du second :
majparsh
#!/bin/sh
if [ $# -ne 1 ]; then
echo "preciser le fichier a traiter"
exit 1
fi

nomfe=$1
nomfm=temp.tmp

./majuscul < $nomfe > $nomfm
./par 8 < $nomfm
rm -f $nomfm
excution :
$ ./majparsh bonjour1.txt
BONJOUR
MONSIEUR

Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
11
fils
0
1
2
fe fm
fils
Il est possible de crer un programme C qui effectue la mme fonction. Il faut rediriger
lentre et la sortie du premier fils (excutant majuscul) et lentre standard du second fils
(excutant par).

Ouverture dun fichier
int open (const char* pathname, int flags, mode_t mode) (voir : man open)

pathname nom du fichier ouvrir
flags options dans louverture du fichier :
O_RDONLY ouverture en lecture
O_WRONLY ouverture en criture
O_CREAT cration du fichier sil nexiste pas
O_TRUNC vider le fichier sil nest pas vide

mode Prcise les droits daccs du fichier crer : (avec des constantes
symboliques comme : S_IRUSR 400, S_IWGRP 20, dfinit dans
<sys/stat.h>)
u g o
r w x r w x r w x
400 200 100 40 20 10 4 2 1

dup2(d,1) : redirige le descripteur 1 (sortie standard) vers le descripteur d
unlink : supprime un fichier (lien)























1
0

majuscul
1
0

par
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
12
0
1
2
fm











majparc.c
#include<stdio.h>
#include<fcntl.h> /* O_RDONLY, O_WRONLY, 0_CREAT */
#include<unistd.h> /* fork, dup2, execlp */
#include<sys/wait.h> /* wait */
main(int argc, char* argv[])
{
char* nomfe;
char nomfm[100]; /* nom du fichier temporaire */

if (argc !=2)
{printf ("specifier le fichier a traiter");exit(1);}

nomfe=argv[1];
sprintf(nomfm,"temp.tmp");

if(fork()==0){
int fe=open(nomfe,O_RDONLY);
if(fe==-1){perror("pb ouverture de fe"); exit(1);}
dup2(fe,0);
int fm=open(nomfm,O_WRONLY | O_TRUNC | O_CREAT, 0666);
if(fm==-1){perror("pb ou verture de fm"); exit(1);}
dup2(fm,1);
execlp("./majuscul","./majuscul",NULL);
perror ("pb de execlp");
exit(1);
}

wait(0);

if (fork()==0){
int fm=open(nomfm,O_RDONLY);
if (fm==-1){perror("pb ouverture de fm");exit(1);}
dup2(fm,0);
unlink(nomfm);
execlp("./par","./par","8",NULL);
perror("pb de execlp");
exit(1);
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
13
}
wait(0);
}
excution :
$ ./majparc bonjour1.txt
BONJOUR
MONSIEUR
1.3.3. Redirection des entres et des sorties sur un tube
1.3.3.1. Faire communiquer deux processus
Les deux processus majuscul et par peuvent communiquer laide dun tube. Le script bash
serait :
majparsh
#!/bin/sh
if [ $# -ne 1 ]; then
echo "preciser le fichier a traiter"
exit 1
fi
nomfe=$1
./majuscul < $nomfe | ./par 8
excution :
$ ./majparsh2 bonjour1.txt
BONJOUR
MONSIEUR












Communication par tube entre 2 processus

Le programme majparc2.c ralise la mme fonction :
majparc2.c
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
main(int argc, char* argv[])
{
char* nomfe;
int p[2];
par
1 0
majuscul
0 1
pre
0
1
2
p[0]
p[1]
fils
0
fe
p[0]
p[1]
1
2
tube p
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
14

if(argc !=2)
{printf ("specifier le fichier traiter"); exit(1);}

nomfe=argv[1];

if(pipe(p)==-1)
{perror("pipe"); exit (1);}

if(fork()==0){ /* fils */
int fe=open(nomfe,O_RDONLY);
if(fe==-1){perror("ouverture de fe");exit(1);}
dup2(fe,0); /* entree standard = nomfe */
dup2(p[1],1); /* sortie standard = tube */
close(fe); /* fe est devenu inutil */
close(p[0]); /* le fils ne lit pas dans le tube */
close(p[1]); /* p[1] est devenu inutil */
execlp("./majuscul","./majuscul",NULL);
perror("Pb avec execlp majuscul");
exit(1);
}

/* pere */
dup2(p[0],0); /* entree standard = tube */
close(p[0]); /* p[0] est devenu inutil */
close(p[1]); /* le pere necrit pas dans le tube */
execlp("./par","./par","8",NULL);
perror("Pb avec execlp par");
exit(1);
}
Excution
$ ./majparc2 bonjour1.txt
BONJOUR
MONSIEUR
1.3.3.2. Rcuprer un rsultat dexcution











tube unidirectionnel
date
0 1
pre
0
1
2
p[0]
p[1]
fils
0
p[0]
p[1]
1
2
tube p
Chapitre 1. Les appels systme pour les processus

Prof. C.EL AMRANI Programmation systme sous UNIX
15
lecture et criture de caractres : read, write
ssize_t read (int fd, void* buf, size_t count) ;
ssize_t write (int fd, void* buf, size_t count) ;
avec :
fd Numro de descripteur
buf Adresse mmoire
count Nombre de caractres lu

tubedate.c
#include<stdio.h>
#include<unistd.h>
#include<wait.h>
main()
{
int i, p[2];
char c, res[50];

if(pipe(p)==-1){perror("Pb tube");exit(1);}

/* fils */
if(fork()==0){
dup2(p[1],1);
close(p[0]);
close(p[1]);
execlp("date","date","+%d/%m/%Y",NULL);
perror("Pb avec execlp date");
exit(1);
}
/* pere */
close(p[1]);
i=0;
while(read(p[0],&c,1)!=0)
{res[i++]=c;}
res[i-1]=0; /* supprime le \n */
printf("Date du jour: %s\n",res);
close(p[0]);
//wait(0);
}

Vous aimerez peut-être aussi