Cours
Cours
Programmation système
sous Unix en C
Franck Pommereau
Licence 2 informatique
Franck Pommereau Introduction • À propos du cours 2 / 172
sur les
Android, iOS, MacOS, Web, IoT, HPC, . . .
Gartner, 2015
▶ équipements
Pourquoi C ?
▶ Unix est programmé en C
▶ C a été développé pour Unix
Objectifs : comprendre les mécanismes de base
▶ système de fichiers
▶ entrées/sorties
▶ processus
Franck Pommereau Introduction • À propos du cours 3 / 172
Travail attendu
▶ prendre des notes en cours ce qui est dit et qui n’est pas sur les diapos
▶ comprendre et connaître le cours
☞ le par-cœur n’est ni nécessaire ni suffisant
▶ préparer et réaliser les travaux pratiques
☞ assister au séances est nécessaire mais pas suffisant
▶ chercher des informations/explications supplémentaires :
▶ les livres de la bibliothèque universitaire
▶ sites Web
▶ sur les appels système : les pages de manuel (man)
▶ sur le langage C : beaucoup de tutoriels/cours en ligne
recoupez les informations
▶ vos enseignant·e·s
▶ posez des questions
▶ demandez des précisions
▶ vérifiez que vous comprenez
▶ ...
Franck Pommereau Introduction • À propos du cours 4 / 172
Origines d’Unix
Unix et ∗nix
1970 1980 1990 2000 2010 Time
FreeBSD 12.0
NetBSD 8.1
BSD family
OpenBSD 6.6
Theo de Raadt
BSD (Berkeley Software Distribution) 4.4
Bill Joy
SunOS 4.1.4
Darwin 19.0
NextStep 3.3
macOS 10.15
Xenix OS Apple
Microsoft/SCO
GNU/Hurd 0.9
GNU
Richard Stallman Linux 5.3
Minix Linus Torvalds
3.4
Andrew S. Tanenbaum
AIX 7.2
IBM
IRIX 6.5.30
SGI
Franck Pommereau Introduction • Unix 9 / 172
POSIX
Portable Operating System Interface/UniX (IEEE 1003)
Structure générale
applications
shell
appels systèmes
noyau
bibliothèques
Franck Pommereau Introduction • Unix 11 / 172
Identités et privilèges
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Rappels de C • 16 / 172
Sommaire
Rappels de C
Compilation
Contrôle de flot
Types et constructeurs de types
Erreurs
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Rappels de C • Compilation 17 / 172
Sommaire
Rappels de C
Compilation
Contrôle de flot
Types et constructeurs de types
Erreurs
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Rappels de C • Compilation 18 / 172
printf 3
Hello world !
hello.c
1 #include <stdio.h>
2
3 int main (void) { // commentaire
4 printf("Hello world!\n"); /* commentaire aussi */
5 }
dans ce cours
▶ on utilise GCC et Bash sous GNU/Linux
▶ autre compilateur/shell ⇒ autre commandes (mais mêmes principes)
Franck Pommereau Rappels de C • Compilation 19 / 172
scanf 3
Compilation séparée free 3
hello-read.c hello.h
1 #include <stdio.h> 1 char* readname (char*);
2 char *readname (char *msg) { 2 void printhello (char*);
3 char *txt; hello-main.c
4 printf("%s ", msg); 1 #include <stdlib.h>
5 scanf("%ms", &txt); 2 #include "hello.h"
6 return txt; 3 int main (void) {
7 } 4 char *name = readname("Tki?");
hello-print.c 5 printhello(name);
1 #include <stdio.h> 6 free(name);
2 void printhello (char *name) { 7 }
3 printf("Hello %s!\n", name);
4 }
$ gcc -c hello-read.c
$ gcc -c hello-print.c
$ gcc -c hello-main.c
$ gcc -o hello hello-read.o hello-print.o hello-main.o
$ ./hello
Tki? Bélix
Hello Bélix!
$
Franck Pommereau Rappels de C • Compilation 20 / 172
Sommaire
Rappels de C
Compilation
Contrôle de flot
Types et constructeurs de types
Erreurs
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Rappels de C • Contrôle de flot 22 / 172
Contrôle de flot
Fonctions
▶ prototype ⇒ dans les fichiers .h
1 int max (int, int); // max a le type int(int,int)
2 void swap (int*, int*); // swap a le type void(int*,int*)
▶ déclaration ⇒ avec le nom des paramètres et le corps
1 int max (int a, int b) {
2 if (a > b) {
3 return a;
4 } else {
5 return b;
6 }
7 }
▶ passage “par valeur” des paramètres ⇒ copiés sur la pile
▶ passage “par adresse” ⇒ explicite par des pointeurs
1 void swap (int *a, int *b) {
2 int t = *a;
3 *a = *b;
4 *b = t;
5 }
▶ pas de fonctions imbriquées
Franck Pommereau Rappels de C • Contrôle de flot 24 / 172
next(2)
int n = 2
4
5 int next (int n) {
6 sum += n;
▶7 return n+1; int n = ?
main
8 }
9 int i = 1
10 int main (void) {
int i, n; int sum = 2
runtime
11
12 for (i=1; i<10; i++) {
13 n = next(i+1); ...
14 printf("%i+1 => %i\n", i, n);
15 } pendant l’appel à
16 printf("sum = %i\n", sum); next(i+1), pour i=1, juste
17 // ... avant le return ligne 7
18 }
Franck Pommereau Rappels de C • Types et constructeurs de types 25 / 172
Sommaire
Rappels de C
Compilation
Contrôle de flot
Types et constructeurs de types
Erreurs
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Rappels de C • Types et constructeurs de types 26 / 172
Pointeurs
▶ déclaration d’un type pointeur
1 int *p; // p est un pointeur sur une valeur de type int
▶ accès à la valeur pointé (déréférencement)
1 *p = 5; // affectation de 5 à la valeur pointée par p
2 int q = (*p) / 2;
▶ opérateur “adresse de”
1 p = &q; // p pointe sur la variable q
2 *p == q; // vrai puisque c'est le même int en mémoire
▶ pointeur sur fonction
1 int (*cmp)(int, int); // cmp est un pointeur sur int(int,int)
2 cmp = max; // si on a défini: int max(int,int)
▶ “int* nom” ou “int *nom” ?
▶ les programmeuses issues du C préfèrent “int *nom” car “*nom est de type int”
▶ les programmeurs issus d’autres langages préfèrent “int* nom” car “nom est de type int*”
▶ les deux sont équivalents et corrects ⇒ moyen mnémotechnique pour la position de *
Franck Pommereau Rappels de C • Types et constructeurs de types 27 / 172
Types énumérés
Structures
Types unions
▶ définition d’un type anypixel pour différents modes de couleurs
1 typedef union { 12 float s;
2 colormode mode; 13 float l;
3 struct { 14 } hsl;
4 colormode mode; 15 struct {
5 unsigned char r; 16 colormode mode;
6 unsigned char g; 17 unsigned char c;
7 unsigned char b; 18 unsigned char y;
8 } rgb; 19 unsigned char m;
9 struct { 20 unsigned char k;
10 colormode mode; 21 } cymk;
11 float h; 22 } anypixel;
▶ pas de nom après union ⇒ anypixel uniquement
▶ utilisation comme des struct imbriqués
1 anypixel p; p.mode = RGB; p.rgb.r = 0;
▶ superposition en mémoire
⇒ &(p.mode) == &(p.rgb.mode) == &(p.hls.mode)
Franck Pommereau Rappels de C • Types et constructeurs de types 32 / 172
Tableaux
▶ tableau = suite de valeurs de même type consécutives en mémoire
67 98 78 73 85 38 29 6 9 47
0 1 2 3 4 5 6 7 8 9
▶ un tableau se définit donc par :
▶ le type des valeurs ⇒ la taille des cases
▶ l’adresse de la première valeur
▶ le nombre de valeurs
▶ C n’a pas de type tableaux
▶ on utilise des pointeurs
▶ il manque le nombre de valeurs
▶ on peut écrire hors des bornes
d’un “tableau”
▶ solution partielle : utiliser un marqueur de fin
▶ comme dans les chaînes char*
▶ on “sacrifie” une valeur (pas toujours possible)
▶ attention à la “vraie” taille des chaînes
Franck Pommereau Rappels de C • Types et constructeurs de types 32 / 172
Tableaux
▶ tableau = suite de valeurs de même type consécutives en mémoire
67 98 78 73 85 38 29 6 9 47
0 1 2 3 4 5 6 7 8 9
▶ un tableau se définit donc par :
▶ le type des valeurs ⇒ la taille des cases
▶ l’adresse de la première valeur
▶ le nombre de valeurs
▶ C n’a pas de type tableaux
▶ on utilise des pointeurs
▶ il manque le nombre de valeurs
▶ on peut écrire hors des bornes
d’un “tableau”
▶ solution partielle : utiliser un marqueur de fin
▶ comme dans les chaînes char*
▶ on “sacrifie” une valeur (pas toujours possible)
▶ attention à la “vraie” taille des chaînes
Franck Pommereau Rappels de C • Types et constructeurs de types 33 / 172
memset 3
“Tableaux” statiques sur la pile
▶ taille fixée à la compilation
▶ mémoire allouée et libérée automatiquement sur la pile
▶ pointeur “constant”
sieve.c
1 #include <stdio.h>
2 #include <string.h>
3
4 void sieve () {
5 unsigned char prime[500]; // taille figée à la compilation
6 int i, p;
7 memset(prime, 1, sizeof(prime)); // sizeof = taille en octets
8 for (p=2; p<500; p++) {
9 if (prime[p]) {
10 printf("%u\n", p);
11 for (i=p; i<500; i+=p) {
12 prime[i] = 0;
13 }
14 }
15 }
16 }
Franck Pommereau Rappels de C • Types et constructeurs de types 34 / 172
Sommaire
Rappels de C
Compilation
Contrôle de flot
Types et constructeurs de types
Erreurs
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Rappels de C • Erreurs 37 / 172
errno 3
Gestion des erreurs perror 3
strerror 3
Sommaire
Rappels de C
Environnement du programme
Invocation
Terminaison
stdio
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Environnement du programme • Invocation 39 / 172
Sommaire
Rappels de C
Environnement du programme
Invocation
Terminaison
stdio
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Environnement du programme • Invocation 40 / 172
La ligne de commande
▶ dans le shell, on tape une ligne de commande
$ ./monprog -a -l --print hello world
▶ le shell interprète certains caractères (*, $, . . .)
▶ le shell découpe cette ligne en tableau de chaînes (selon les espaces)
./monprog -a -l --print hello world
▶ ce tableau est passé au programme (qui doit se débrouiller avec)
▶ int main(void) ⇒ le programme ignore les paramètres
▶ sinon, on doit avoir :
1 #include <stdio.h>
2
3 int main (int argc, char *argv[]) { // ou char **argv
4 // argc = 6
5 // argv = {"./monprog", "-a", "-l", "--print", "hello", "world"}
6 for (int i=0; i<argc; i++) {
7 printf("%s\n", argv[i]);
8 }
9 }
Franck Pommereau Environnement du programme • Invocation 41 / 172
Sommaire
Rappels de C
Environnement du programme
Invocation
Terminaison
stdio
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Environnement du programme • Terminaison 44 / 172
Code de retour
▶ main retourne toujours un int
1 int main(void);
2 int main(int, char*[]);
3 int main(int, char*[], char*[]);
▶ la valeur retournée est passée au shell (qui la met dans $?)
int-main.c
1 int main (void) {
2 return 123;
3 }
$ gcc int-main.c
$ ./a.out
$ echo $?
123
$
▶ exit(123) aurait le même effet
▶ partout dans le programme (return code ne fonctionne que pour main)
▶ termine le processus
Franck Pommereau Environnement du programme • stdio 45 / 172
Sommaire
Rappels de C
Environnement du programme
Invocation
Terminaison
stdio
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Environnement du programme • stdio 46 / 172
fscanf 3
Les entrées/sorties standards fprintf 3
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • Concepts 48 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • Concepts 49 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • Méta-données 52 / 172
Attributs spéciaux
▶ sur un fichier :
▶ bit setuid : -rwsrwxrwx
▶ le fichier est un programme exécutable
▶ le processus aura l’uid de l’utilisateur propriétaire du fichier
▶ bit setgid : -rwxrwsrwx
▶ le fichier est un programme exécutable
▶ le processus aura le gid du groupe propriétaire du fichier
▶ sur un répertoire :
▶ bit setuid : drwsrwxrwx
▶ un fichier ajouté aura comme utilisateur propriétaire celui du répertoire
▶ hérité par les sous-répertoires
▶ bit setgid : drwxrwsrwx
▶ un fichier ajouté aura comme groupe propriétaire celui du répertoire
▶ hérité par les sous-répertoires
▶ sticky bit : drwxrwxrwt
▶ un fichier ne pourra être supprimé que par son propriétaire
Franck Pommereau Le système de fichiers • Méta-données 54 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • inodes 57 / 172
Représentation interne
▶ les disques physiques sont partitionnés
▶ les partitions sont formatées
▶ chacune = un volume avec un identifiant
▶ les volumes sont montés dans l’arborescence
▶ chaque objet d’un volume est représenté par un inode
▶ chacun a son numéro
▶ contient les métadonnées du fichier (sauf son nom)
▶ type de fichier
▶ les attributs (permissions, propriétaire, taille, dates, etc.)
▶ position dans le volume (selon formatage/technologie du disque physique)
▶ nombre de liens
▶ nombre d’utilisations (fichiers ouverts)
▶ ...
▶ un fichier ou répertoire est identifié de façon unique par son identifiant de volume et son
numéro d’inode
▶ un répertoire est un fichier particulier contenant une liste de :
nom 7→ n° inode
Franck Pommereau Le système de fichiers • inodes 58 / 172
stat 1
Visualiser les inodes dans le shell
$ stat *
File: autre-lien -> fichier
Size: 7 Blocks: 0 IO Block: 4096 symbolic link
Device: fd01h/64769d Inode: 8913103 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ franck) Gid: ( 1000/ franck)
Access: 2021-11-15 14:26:06.888014343 +0100
Modify: 2021-11-15 14:26:04.180040375 +0100
Change: 2021-11-15 14:26:04.180040375 +0100
Birth: -
File: fichier
Size: 1197060 Blocks: 2344 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 8913100 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ franck) Gid: ( 1000/ franck)
Access: 2021-11-15 14:25:50.760169942 +0100
Modify: 2021-11-15 14:25:50.760169942 +0100
Change: 2021-11-15 14:25:56.296116377 +0100
Birth: -
File: un-lien
Size: 1197060 Blocks: 2344 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 8913100 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ franck) Gid: ( 1000/ franck)
Access: 2021-11-15 14:25:50.760169942 +0100
Modify: 2021-11-15 14:25:50.760169942 +0100
Change: 2021-11-15 14:25:56.296116377 +0100
Birth: -
Franck Pommereau Le système de fichiers • Navigation et répertoires 59 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • Navigation et répertoires 60 / 172
getcwd 3
Le répertoire de travail actuel chdir 3
1 #include <sys/types.h>
2 #include <dirent.h>
3
4 DIR *opendir(const char *name);
5 int closedir(DIR *dirp);
6 void rewinddir(DIR *dirp);
1 #include <sys/types.h>
2 #include <dirent.h>
3
4 struct dirent *readdir(DIR *dirp);
1 #include <sys/stat.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4
5 int mkdir(const char *pathname, mode_t mode);
6 int rmdir(const char *pathname);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • API méta-données 66 / 172
stat 2
struct stat
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <unistd.h>
4
5 int stat(const char *pathname, struct stat *statbuf);
6 int lstat(const char *pathname, struct stat *statbuf);
7 int fstat(int fd, struct stat *statbuf);
1 #include <sys/stat.h>
2
3 int chmod(const char *pathname, mode_t mode);
4 int fchmod(int fd, mode_t mode);
Les “variantes f”
▶ on a vu chmod 2 et fchmod 2
▶ il existe beaucoup d’autres cas similaires
▶ on ne les verra pas systématiquement
▶ RTFM (read the f. . .ine manual)
▶ la “variante f” est :
▶ plus rapide
(une seul résolution du chemin à l’ouverture du fichier)
▶ plus sûre en environnement concurrent
(le chemin peut être changé par un autre processus)
▶ inutile pour une modification ponctuelle
Franck Pommereau Le système de fichiers • API méta-données 72 / 172
chown 2
chown(), fchown(), et lchown() fchown 2
lchown 2
1 #include <unistd.h>
2
3 int chown(const char *pathname, uid_t owner, gid_t group);
4 int fchown(int fd, uid_t owner, gid_t group);
5 int lchown(const char *pathname, uid_t owner, gid_t group);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Concepts
Méta-données
inodes
Navigation et répertoires
API méta-données
API liens
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Le système de fichiers • API liens 75 / 172
link 2
link() et symlink() symlink 2
1 #include <unistd.h>
2
3 int link(const char *oldpath, const char *newpath);
4 int symlink(const char *target, const char *linkpath);
1 #include <unistd.h>
2
3 ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
▶ écrit la destination du lien symbolique pathname dans buf qui doit avoir la taille bufsiz
▶ n’ajoute pas '\0' à la fin de buf
▶ si buf est trop petit, la destination sera tronquée
▶ renvoie le nombre de char lus en cas de succès, -1 sinon (avec errno)
▶ si bufsize est renvoyé, la destination peut-être tronquée
▶ la taille requise peut-être obtenue avec lstat 2 dans le champ st_size du struct stat
utilisé
(à condition que le lien symbolique ne change pas entre les deux appels)
Franck Pommereau Le système de fichiers • API liens 77 / 172
unlink 2
unlink()
1 #include <unistd.h>
2
3 int unlink(const char *pathname);
▶ supprime un lien
▶ l’inode correspondant a un lien de moins
▶ si c’était le dernier, l’inode est libéré ⇒ peut servir à d’autres fichiers
▶ équivalent à la commande shell rm pathname
▶ pathname est un lien symbolique
⇒ supprimé sans affecter sa cible
▶ fichier ouvert par des processus
⇒ sera vraiment effacé lorsque tous les processus l’auront fermé
▶ ne fonctionne pas sur les répertoires (voir rmdir 3 plus tard)
▶ renvoie 0 en cas de succès, -1 sinon (avec errno)
Franck Pommereau Le système de fichiers • API liens 78 / 172
rename 2
rename()
1 #include <stdio.h>
2
3 int rename(const char *oldpath, const char *newpath);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
API
Représentation interne
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Entrées/sorties • API 81 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
API
Représentation interne
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Entrées/sorties • API 82 / 172
Fichiers
1 #include <unistd.h>
2
3 ssize_t read(int fd, void *buf, size_t count);
1 #include <unistd.h>
2
3 ssize_t write(int fd, const void *buf, size_t count);
1 #include <unistd.h>
2
3 int fsync(int fd);
4 void sync(void);
1 #include <sys/types.h>
2 #include <unistd.h>
3
4 off_t lseek(int fd, off_t offset, int whence);
1 #include <unistd.h>
2 #include <sys/types.h>
3
4 int ftruncate(int fd, off_t length);
1 #include <unistd.h>
2
3 int close(int fd);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
API
Représentation interne
Les processus
Communications entre processus
Threads POSIX
Franck Pommereau Entrées/sorties • Représentation interne 92 / 172
int fd 4
pid: 1215
file descriptors: status: W
0 offset: 10
stdin < foo.txt 1 inode ptr: type: reg file
2 inode nbr: …
4 > bar.log 3 refcount: 1
4 ref count: 2
5
6
…
status: R
processus 1215
offset: 8
pid: 1421 inode ptr:
int fd 4 refcount: 1
file descriptors: type: reg file
0 inode nbr: …
1 ref count: 1
2
3
4
status: W
4 > foo.txt 5 offset: 51
6
… inode ptr:
refcount: 1
ý back
Franck Pommereau Entrées/sorties • Représentation interne 93 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Concepts
API infos
API cycle de vie
Identités
Communications entre processus
Threads POSIX
Franck Pommereau Les processus • Concepts 95 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Concepts
API infos
API cycle de vie
Identités
Communications entre processus
Threads POSIX
Franck Pommereau Les processus • Concepts 96 / 172
▶ chaque processus est identifié par un numéro > 0 de type pid_t (généralement un int)
▶ à chaque instant, le pid de chaque processus est unique
▶ mais un même pid peut être réutilisé plus tard pour un autre processus
▶ une seule façon de créer un nouveau processus : fork 2
▶ duplique le processus qui l’appelle
⇒ un processus parent et un enfant (arbre des processus)
▶ l’enfant peut se remplacer par un autre programme avec exec 2
▶ la séquence fork(); exec() permet de lancer un programme
▶ le premier processus init est créé de façon spéciale
(init a le pid 1 et démarre tout le système)
▶ un processus qui termine devient un zombie
▶ état mort-vivant permettant de consulter son statut de terminaison
▶ un autre processus peut consulter cet état avec wait 2
⇒ le zombie est éliminé
▶ si un parent termine avant ses enfants, ils sont rattachés à init
Franck Pommereau Les processus • Concepts 97 / 172
no memory
available
ready to run wakeup sleeping
swapped swapped
Franck Pommereau Les processus • API infos 98 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Concepts
API infos
API cycle de vie
Identités
Communications entre processus
Threads POSIX
Franck Pommereau Les processus • API infos 99 / 172
getpid 2
getpid() et getppid() getppid 2
1 #include <sys/types.h>
2 #include <unistd.h>
3
4 pid_t getpid(void);
5 pid_t getppid(void);
1 #include <unistd.h>
2
3 char *getcwd(char *buf, size_t size);
1 #include <unistd.h>
2
3 int chdir(const char *path);
▶ écrit les temps d’exécution du processus et des ses enfants dans buf
▶ distingue temps utilisateur et temps système (état user/kernel running)
▶ uniquement les enfants dont le processus a collecté l’état (wait 2 )
▶ temps comptés en tics d’horloge
sysconf(_SC_CLK_TCK) ⇒ nombre de tics par seconde
▶ renvoie une valeur arbitraire en cas de succès, -1 sinon (avec errno)
Franck Pommereau Les processus • API infos 102 / 172
setpgid 2
Sessions et groupes de processus getpgid 2
setsid 2
getsid 2
▶ groupe : pgid ⇒ ensemble de processus qui travaillent ensemble
▶ session : sid ⇒ ensemble de processus issus d’un même terminal (session utilisateur)
▶ ces identifiants sont des pids
▶ certains appels systèmes agissent sur un groupe ou une session
1 #include <sys/types.h>
2 #include <unistd.h>
3
4 int setpgid(pid_t pid, pid_t pgid);
5 pid_t getpgid(pid_t pid);
6
7 pid_t setsid(void);
8 pid_t getsid(pid_t pid);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Concepts
API infos
API cycle de vie
Identités
Communications entre processus
Threads POSIX
Franck Pommereau Les processus • API cycle de vie 104 / 172
exit 2
exit()
1 #include <stdlib.h>
2
3 void exit(int status);
Recouvrement
1 #include <unistd.h>
2
3 int execl(const char *pathname, const char *arg, ...
4 /* (char*) NULL */);
5 int execlp(const char *file, const char *arg, ...
6 /* (char*) NULL */);
7 int execle(const char *pathname, const char *arg, ...
8 /* (char*) NULL, char *const envp[] */);
▶ commande à lancer
▶ chemin (execl, execle) ou nom (exclp) du programme
▶ les arguments y compris argv[0]
▶ fin des arguments marquée par NULL
▶ par exemple :
1 ret = execl("/usr/bin/gcc", "gcc", "-c", "monprog.c", NULL);
2 ret = execlp("gcc", "gcc", "-c", "monprog.c", NULL);
3
4 char *env[] = {"TMPDIR=.", NULL};
5 ret = execle("/usr/bin/gcc", "gcc", "-c", "monprog.c", NULL, env);
Franck Pommereau Les processus • API cycle de vie 111 / 172
execv 3
execv(), execvp(), et execve() execvp 3
execve 2
1 #include <unistd.h>
2
3 int execv(const char *pathname, char *const argv[]);
4 int execvp(const char *file, char *const argv[]);
5 int execve(const char *pathname, char *const argv[],
6 char *const envp[]);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Concepts
API infos
API cycle de vie
Identités
Communications entre processus
Threads POSIX
Franck Pommereau Les processus • Identités 113 / 172
setuid 2
Les identités d’un processus
▶ chaque processus est identifié par
▶ real user id : ruid (programmes setuid)
▶ effective user id : euid ⇒ contrôle des permissions
▶ saved user id : suid
▶ changement d’identité avec setuid(id) ⇒ autorisé si
▶ euid == 0 ou euid == id (ou la capacité CAP_SETUID)
▶ ou si suid == id (suid permet le retour en arrière)
et alors : suid = euid = ruid = id
▶ programme setuid ⇒ affecte euid du processus
1 #include <unistd.h>
2 #include <sys/types.h>
3
4 uid_t getuid(void);
5 uid_t geteuid(void);
6 int setuid(uid_t uid);
Démons
▶ processus qui s’exécute en tâche de fond
▶ fork() et rattachement à init
▶ positionne divers paramètres
▶ condamne ses entrées-sorties standards
1 pid_t pid = fork();
2 if (pid == -1) {
3 exit (EXIT_FAILURE); // fork() a échoué => tout échoue
4 } else if (pid != 0) {
5 exit (EXIT_SUCCESS); // fork a réussi => le parent termine
6 } // => l'enfant est rattaché à init
7 /* - setsid()
8 - chdir()
9 - setuid()
10 - ... */
11 // ferme les entrées-sorties standards
12 // d'autres techniques les condamnent: dup2()
13 close(STDIN_FILENO);
14 close(STDOUT_FILENO);
15 close(STDERR_FILENO);
Franck Pommereau Communications entre processus • 116 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • Fichiers 117 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • Fichiers 118 / 172
Tester un verrou
getlock.c
1 #include <sys/types.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4
5 pid_t get_lock (int fd, short type, short whence, off_t start, off_t len) {
6 struct flock lock = {.l_type = type, .l_whence = whence,
7 .l_start = start, .l_len = len};
8 if (fcntl(fd, F_GETLK, &lock) < 0) {
9 return -1; // error => caller will check errno
10 }
11 if (lock.l_type == F_UNLCK) {
12 return 0; // no conflicting lock found
13 } else {
14 return lock.l_pid; // lock found => return owner's pid
15 }
16 }
▶ aucun verrou incompatible trouvé ⇒ 0 (ignore les verrous du processus, ou d’autres en lecture)
▶ verrou incompatible trouvé ⇒ pid du processus propriétaire
▶ erreur ⇒ -1 (avec errno)
Franck Pommereau Communications entre processus • Fichiers 122 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • Signaux 124 / 172
Signaux
▶ signal = évènement
▶ envoyé à un ou plusieurs processus
▶ ne transporte pas de données
▶ mais plusieurs signaux possibles
▶ un signal tue le processus s’il n’est pas prêt à le recevoir
▶ envoyer un signal dans le shell :
$ xeyes &
[1] 143967
$ kill -ALRM 143967
[1]+ Alarm clock xeyes
$
▶ xeyes est lancé avec le pid 143967
▶ kill envoie le signal ALARM à ce processus
▶ xeyes meurt car il ne s’attendait pas à recevoir un signal
▶ le shell sait qu’il a été tué par le signal Alarm clock
▶ touches spéciales dans le terminal :
Ctrl + Z ⇒ STOP Ctrl + C ⇒ INT Ctrl + \ ⇒ QUIT
Franck Pommereau Communications entre processus • Signaux 125 / 172
kill 2
kill() signal 7
1 #include <sys/types.h>
2 #include <signal.h>
3
4 int kill(pid_t pid, int sig);
▶ envoie un signal sig au processus pid
▶ pid est un numéro de processus (>0) ou bien :
▶ 0 ⇒ tous les processus du même groupe
▶ -1 ⇒ tous les processus (pour lesquels c’est autorisé, et sauf init)
▶ <-1 ⇒ tous les processus du groupe -pid
▶ autorisé vers les processus de même uid
(ou tous les processus si privilégié)
▶ renvoie 0 en cas de succès, -1 en cas d’erreur (avec errno)
▶ signal.h définit des noms de signaux :
SIGALRM, SIGINT, SIGKILL, . . . (voir la liste dans signal 7 )
▶ SIGKILL et SIGSTOP ne peuvent pas être interceptés
Franck Pommereau Communications entre processus • Signaux 126 / 172
sigaction 2
Recevoir un signal signal 7
1 #include <signal.h>
2
3 struct sigaction {
4 void (*sa_handler)(int);
5 int sa_flags;
6 // ...
7 };
8
9 int sigaction(int signum, const struct sigaction *act,
10 struct sigaction *oldact);
▶ active le traitant act et récupère le précédent dans oldact
▶ act.sa_handler est un pointeur sur une fonction void (int)
▶ act.sa_flags indique comment gérer le traitant : (combiner avec |)
▶ SA_NODEFER ⇒ un nouveau signal peut être reçu pendant le traitant
▶ SA_RESETHAND ⇒ le traitant sera désinstallé à réception de signum
▶ SA_RESTART ⇒ le traitant sera réinstallé à réception de signum
▶ renvoie 0 en cas de succès, -1 en cas d’erreur (avec errno)
▶ l’appel système signal 2 est plus simple mais pas portable
Franck Pommereau Communications entre processus • Signaux 127 / 172
signal.c signal.c
1 #include <signal.h> 15 int main (void) {
2 #include <stdio.h> 16 struct sigaction act;
3 #include <stdlib.h> 17 act.sa_handler = exit_on_sig;
4 #include <unistd.h> 18 sigaction(SIGINT, &act, NULL);
5 19 act.sa_handler = print_on_sig;
6 void exit_on_sig (int sig) { 20 act.sa_flags = SA_RESTART;
7 printf("! %i\n", sig); 21 sigaction(SIGQUIT, &act, NULL);
8 exit(0); 22 printf("= %i\n", getpid());
9 } 23 while (1) {
10 24 sleep(1);
11 void print_on_sig (int sig) { 25 }
12 printf("? %i\n", sig); 26 }
13 } 27
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • Pipes 129 / 172
ls grep sed
stderr stderr stderr
¥
Franck Pommereau Communications entre processus • Pipes 130 / 172
pipe 2
pipe() pipe 7
1 #include <unistd.h>
2
3 int pipe(int pipefd[2]);
1 #include <sys/types.h>
2 #include <sys/stat.h>
3
4 int mkfifo(const char *path, mode_t mode);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • IPC système V 135 / 172
sysvipc 7
IPC système V
▶ communications avancées entre processus
▶ files de messages : msg (format libre)
▶ sémaphores : sem (verrous flexibles)
▶ partage de mémoire : shm (segments)
▶ indépendant du système de fichiers
▶ chaque type ⇒ gestion spécifique
▶ identifiant externe (clef) de type key_t (≃ chemin d’un fichier)
▶ identifiant interne de type int (≃ numéro d’un fichier ouvert)
▶ permissions (comme pour les fichiers)
1 #include <sys/ipc.h>
2
3 struct ipc_perm {
4 uid_t cuid; // creator user ID
5 gid_t cgid; // creator group ID
6 uid_t uid; // owner user ID
7 gid_t gid; // owner group ID
8 unsigned short mode; // u/g/o r/w permissions
9 };
Franck Pommereau Communications entre processus • IPC système V 136 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • IPC : files de messages 139 / 172
msgget 2
Files de messages : msgget()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/msg.h>
4
5 int msgget(key_t key, int flags);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • IPC : mémoire partagée 144 / 172
shmget 2
Partage de mémoire : shmget()
1 #include <sys/ipc.h>
2 #include <sys/shm.h>
3
4 int shmget(key_t key, size_t size, int flags);
1 #include <sys/types.h>
2 #include <sys/shm.h>
3
4 void *shmat(int shmid, const void *shmaddr, int shmflg);
5 int shmdt(const void *shmaddr);
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • IPC : sémaphores 148 / 172
Sémaphores
▶ sémaphore = compteur semval avec opérations atomiques
▶ affecter ⇒ semval = p
▶ lire ⇒ donne semval
▶ “prendre” p <= semval ⇒ semval -= p
tant que p > semval ⇒ le processus est bloqué
▶ “rendre” p ⇒ semval += p
▶ attendre 0 ⇒ processus bloqué tant que semval > 0
▶ cas particulier : semval <= 1 ⇒ simple verrou
▶ dans IPC système V ⇒ ensembles de sémaphores
(protéger plusieurs ressources simultanément)
▶ exemple : garantir un maximum de personnes présentes simultanément dans un magasin
ayant plusieurs accès
▶ initialiser un sémaphore au maximum souhaité
▶ entrée ⇒ prendre 1
▶ sortie ⇒ rendre 1
Franck Pommereau Communications entre processus • IPC : sémaphores 149 / 172
semget 2
Sémaphores : semget()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 int semget(key_t key, int nsems, int flags);
▶ ouvre l’ensemble de sémaphores identifié par la clef key
▶ s’il n’existe pas encore :
▶ flags = mode | IPC_CREAT
▶ nsems > 0 ⇒ nombre de sémaphores dans l’ensemble
▶ s’il existe déjà :
▶ on peut utiliser nsems == 0
▶ flags ignoré
▶ key == IPC_PRIVATE ⇒ création sans clef (comme msgget 2 )
▶ IPC_EXCL dans flags ⇒ échoue si l’ensemble existe déjà
▶ renvoie l’identifiant interne en cas de succès
-1 en cas d’erreur (avec errno)
Franck Pommereau Communications entre processus • IPC : sémaphores 150 / 172
semctl 2
Sémaphores : semctl()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct semid_ds {
6 struct ipc_perm sem_perm; // ownership and permissions *
7 time_t sem_otime; // Last semop time
8 time_t sem_ctime; // Last change time
9 unsigned long sem_nsems; // No. of semaphores in set
10 };
11
12 int semctl(int semid, int semnum, int cmd, ... /* arg */ );
▶ opération de contrôle sur l’ensemble semid, selon cmd
⇒ avec semnum ignoré et struct semid_ds *arg
▶ cmd == IPC_STAT ⇒ renseigne args avec le paramétrage courant
▶ cmd == IPC_SET ⇒ change le paramétrage* selon arg
Franck Pommereau Communications entre processus • IPC : sémaphores 150 / 172
semctl 2
Sémaphores : semctl()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct semid_ds {
6 struct ipc_perm sem_perm; // ownership and permissions *
7 time_t sem_otime; // Last semop time
8 time_t sem_ctime; // Last change time
9 unsigned long sem_nsems; // No. of semaphores in set
10 };
11
12 int semctl(int semid, int semnum, int cmd, ... /* arg */ );
▶ opération de contrôle sur l’ensemble semid, selon cmd
⇒ avec semnum ignoré et sans arg
▶ cmd == IPC_RMID ⇒ sans arg, supprime l’ensemble immédiatement
Franck Pommereau Communications entre processus • IPC : sémaphores 150 / 172
semctl 2
Sémaphores : semctl()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct semid_ds {
6 struct ipc_perm sem_perm; // ownership and permissions *
7 time_t sem_otime; // Last semop time
8 time_t sem_ctime; // Last change time
9 unsigned long sem_nsems; // No. of semaphores in set
10 };
11
12 int semctl(int semid, int semnum, int cmd, ... /* arg */ );
▶ opération de contrôle sur l’ensemble semid, selon cmd
⇒ pour le sémaphore d’index semnum dans l’ensemble, sans arg
▶ cmd == GETVAL ⇒ valeur du sémaphore semval
▶ cmd == GETPID ⇒ pid du dernier processus ayant utilisé le sémaphore
▶ cmd == GETNCNT ⇒ nombre de processus attendant semval++
▶ cmd == GETZCNT ⇒ nombre de processus attentant semval == 0
Franck Pommereau Communications entre processus • IPC : sémaphores 150 / 172
semctl 2
Sémaphores : semctl()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct semid_ds {
6 struct ipc_perm sem_perm; // ownership and permissions *
7 time_t sem_otime; // Last semop time
8 time_t sem_ctime; // Last change time
9 unsigned long sem_nsems; // No. of semaphores in set
10 };
11
12 int semctl(int semid, int semnum, int cmd, ... /* arg */ );
▶ opération de contrôle sur l’ensemble semid, selon cmd
⇒ pour le sémaphore d’index semnum dans l’ensemble, avec int arg
▶ cmd == SETVAL ⇒ assigne la valeur du sémaphore
Franck Pommereau Communications entre processus • IPC : sémaphores 150 / 172
semctl 2
Sémaphores : semctl()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct semid_ds {
6 struct ipc_perm sem_perm; // ownership and permissions *
7 time_t sem_otime; // Last semop time
8 time_t sem_ctime; // Last change time
9 unsigned long sem_nsems; // No. of semaphores in set
10 };
11
12 int semctl(int semid, int semnum, int cmd, ... /* arg */ );
▶ opération de contrôle sur l’ensemble semid, selon cmd
⇒ avec semnum ignoré, et unsigned short *arg
▶ cmd == GETALL ⇒ écrit la valeur de tous les sémaphores de l’ensemble dans arg
▶ cmd == GETALL ⇒ assigne la valeur de tous les sémaphores de l’ensemble selon arg
Franck Pommereau Communications entre processus • IPC : sémaphores 150 / 172
semctl 2
Sémaphores : semctl()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct semid_ds {
6 struct ipc_perm sem_perm; // ownership and permissions *
7 time_t sem_otime; // Last semop time
8 time_t sem_ctime; // Last change time
9 unsigned long sem_nsems; // No. of semaphores in set
10 };
11
12 int semctl(int semid, int semnum, int cmd, ... /* arg */ );
▶ opération de contrôle sur l’ensemble semid, selon cmd
▶ renvoie -1 en cas d’erreur (avec errno)
sinon, retour selon cmd
Franck Pommereau Communications entre processus • IPC : sémaphores 151 / 172
semop 2
Sémaphores : semop()
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/sem.h>
4
5 struct sembuf {
6 unsigned short sem_num; // index in the set
7 short sem_op; // operation to apply
8 short sem_flg; // IPC_NOWAIT, SEM_UNDO
9 };
10
11 int semop(int semid, struct sembuf *sops, size_t nsops);
▶ applique de façon atomique les nsops opérations dans sops
▶ .sem_op < 0 ⇒ prend des ressources au sémaphore .sem_num
▶ .sem_op > 0 ⇒ rend des ressources au sémaphore .sem_num
▶ .sem_op == 0 ⇒ attend que le sémaphore .sem_num atteigne zéro
▶ si IPC_NOWAIT dans .sem_flg ⇒ erreur au lieu d’un blocage
▶ si SEM_UNDO dans .sem_flg ⇒ gère un compteur de ressources prises
⇒ rendues si le processus s’arrête (par processus et par sémaphore)
Franck Pommereau Communications entre processus • IPC : conclusion 152 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • IPC : conclusion 153 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Fichiers
Signaux
Pipes
IPC système V
IPC : files de messages
IPC : mémoire partagée
IPC : sémaphores
IPC : conclusion
Sémaphores POSIX
Threads POSIX
Franck Pommereau Communications entre processus • Sémaphores POSIX 155 / 172
sem_overview 7
Sémaphores POSIX ý mutex ý queues
1 #include <semaphore.h>
2
3 int sem_init(sem_t *sem, int pshared, unsigned int value);
4 int sem_destroy(sem_t *sem);
▶ sem_init
▶ nécessite une variable sem_t partagée par les processus
(par exemple dans un segment de mémoire partagé)
▶ pshared == 1 pour un partage entre processus
(0 pour un partage entre threads ⇒ sem peut être une variable globale)
▶ value ⇒ valeur initiale du sémaphore
▶ ne pas utiliser sem_destroy pour un sémaphore sur lequel des processus sont bloqués
▶ renvoient 0 en cas de succès, -1 en cas d’erreur (avec errno)
Franck Pommereau Communications entre processus • Sémaphores POSIX 158 / 172
sem_wait 3
sem_wait(), sem_trywait(), et sem_post() sem_trywait 3
sem_post 3
1 #include <semaphore.h>
2
3 struct timespec {
4 time_t tv_sec; // seconds
5 long tv_nsec; // nanoseconds [0 .. 999999999]
6 };
7
8 int sem_wait(sem_t *sem);
9 int sem_trywait(sem_t *sem);
10 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
11 int sem_post(sem_t *sem);
▶ sem_wait ⇒ prend une ressource en bloque si le sémaphore vaut zéro
▶ sem_trywait ⇒ retourne en erreur au lieu de bloquer
▶ sem_timedwait ⇒ retourne en erreur si bloqué après abs_timeout
(“date” fixe à partir de l’epoch)
▶ sem_post ⇒ rend une resource (et débloque un processus)
▶ renvoient 0 en cas de succès, -1 en cas d’erreur (avec errno)
Franck Pommereau Threads POSIX • 159 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Vue d’ensemble
API de base
Mécanismes de synchronisation
Franck Pommereau Threads POSIX • Vue d’ensemble 160 / 172
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Vue d’ensemble
API de base
Mécanismes de synchronisation
Franck Pommereau Threads POSIX • Vue d’ensemble 161 / 172
pthreads 7
Threads
Processus légers
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Vue d’ensemble
API de base
Mécanismes de synchronisation
Franck Pommereau Threads POSIX • API de base 163 / 172
pthread_self 3p
Identifiants de threads pthread_equal 3p
1 // ldd: -pthread
2 #include <pthread.h>
3
4 pthread_t pthread_self(void);
5 int pthread_equal(pthread_t t1, pthread_t t2);
1 // ldd: -pthread
2 #include <pthread.h>
3
4 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
5 void *(*start_routine) (void *), void *arg);
6 void pthread_exit(void *retval);
1 // ldd: -pthread
2 #include <pthread.h>
3
4 int pthread_join(pthread_t thread, void **retval);
5 int pthread_cancel(pthread_t thread);
Exemple
threads.c threads.c
Sommaire
Rappels de C
Environnement du programme
Le système de fichiers
Entrées/sorties
Les processus
Communications entre processus
Threads POSIX
Vue d’ensemble
API de base
Mécanismes de synchronisation
Franck Pommereau Threads POSIX • Mécanismes de synchronisation 168 / 172
pthread_mutex_lock 3p
Mutex (mutual exclusion) pthread_mutex_unlock 3p
barrier.c barrier.c
mq.c
1 // ldd: -pthread -lrt
2 #include <pthread.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <fcntl.h>
8 #include <mqueue.h>
9
10 struct msg { // stores a message
11 int num;
12 char txt[256];
13 };
14
15 typedef union { // stores a message + raw char* to it
16 struct msg msg;
17 char raw[sizeof(struct msg)];
18 } msg_t;
19
20 mqd_t queue; // shared among threads
21
Franck Pommereau Threads POSIX • Mécanismes de synchronisation 172 / 172
mq.c
22 void* start (void *arg) { // threads activity
23 msg_t msg;
24 while (1) {
25 mq_receive(queue, msg.raw, sizeof(msg_t), NULL);
26 printf("[%i] %i: %s\n", *(int*)arg, msg.msg.num, msg.msg.txt);
27 }
28 }
29
Franck Pommereau Threads POSIX • Mécanismes de synchronisation 172 / 172
mq.c
30 int main (int argc, char *argv[]) {
31 int i;
32 msg_t msg;
33 pthread_t threads[10]; // threads
34 int targs[10]; // threads args
35 struct mq_attr attr = {.mq_maxmsg = argc,
36 .mq_msgsize = sizeof(msg_t)}; // important for mq_receive
37 queue = mq_open("/myqueue", O_RDWR|O_CREAT|O_EXCL, 0660, &attr);
38 for (i=0; i<10; i++) { // create 10 threads
39 targs[i] = i;
40 pthread_create(threads+i, NULL, start, targs+i);
41 }
42 // ...
Franck Pommereau Threads POSIX • Mécanismes de synchronisation 172 / 172
mq.c
43 // main...
44 for (i=1; i<argc; i++) { // send each argv[i] as a message
45 msg.msg.num = i;
46 memset(msg.msg.txt, 0, 256);
47 strncpy(msg.msg.txt, argv[i], 255);
48 mq_send(queue, msg.raw, sizeof(msg_t), 0);
49 }
50 sleep(1); // wait enough for messages to be received
51 for (i=0; i<10; i++) { // terminate threads
52 pthread_cancel(threads[i]); // work when blocked on queue
53 pthread_join(threads[i], NULL);
54 }
55 mq_close(queue); // close queue
56 mq_unlink("/myqueue"); // delete queue
57 exit(0);
58 }
Franck Pommereau Threads POSIX • Mécanismes de synchronisation 172 / 172