0% ont trouvé ce document utile (0 vote)
54 vues18 pages

IPC System V sous Unix : Mémoire Partagée

Le document traite des mécanismes de communication entre processus (IPC) dans UNIX System V, incluant la mémoire partagée, les sémaphores et les files de messages. Il explique comment créer, attacher, détacher et contrôler des segments de mémoire partagée, ainsi que le principe des sémaphores. Des exemples de code illustrent la création et l'utilisation de ces mécanismes IPC.

Transféré par

mohamedammar.bellah
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
54 vues18 pages

IPC System V sous Unix : Mémoire Partagée

Le document traite des mécanismes de communication entre processus (IPC) dans UNIX System V, incluant la mémoire partagée, les sémaphores et les files de messages. Il explique comment créer, attacher, détacher et contrôler des segments de mémoire partagée, ainsi que le principe des sémaphores. Des exemples de code illustrent la création et l'utilisation de ces mécanismes IPC.

Transféré par

mohamedammar.bellah
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Programmation système sous unix 2ème ING-ISI (2011-2012)

Chapitre 4- Les IPC System V

I- Introduction

Les mécanismes de communication entre processus (InterProcess Communication ou IPC)


d’UNIX System V ont été repris dans de nombreuses variantes d’Unix. Il existe trois
mécanismes :

- Les segments de mémoire partagés.


- Les sémaphores.
- Les files de messages.

Ces trois types d’objet sont identifiés par des clés.

Constitution d’une clé

# include <sys/types.h>
# include <sys/ipc.h>

key_t ftok (char *pathname, char proj )

Cette fonction convertit le nom et le chemin d'accès d'un fichier existant, ainsi qu'un
identificateur de projet en une clé IPC Système V de type key_t.
Si elle réussit, la fonction ftok renvoie une valeur de type key_t, sinon elle renvoie -1.

Exemple : On dispose d'une application commune dans /opt/jeux/OuiOui. Cet application


utilise deux objets partagés. On pourra utiliser les clés ftok("/opt/jeux/OuiOui",'A') et
ftok("/opt/jeux/OuiOui",'B'). Ainsi tous les processus de ce logiciel se réfèreront aux
mêmes objets qui seront partagés entre tous les utilisateurs.

II- Les mémoires partagées


Les processus appartenant à des espaces d’adressages disjoints et désirant communiquer,
demandent à partager une zone mémoire dans laquelle ils placent les variables en commun. Le
système d’exploitation leur fournit une zone mémoire à laquelle ils vont se rattacher pour
partager ces variables. Ils devront toutefois gérer les problèmes des accès concurrents.
Chaque segment mémoire est identifié, au niveau du système, par une clé à laquelle
correspond un identifiant. Lorsqu'un segment est attaché à un programme, les données qu'il
contient sont accessibles en mémoire par l'intermédiaire d'un pointeur.
Les primitives pour gérer la mémoire partagée sont définit dans le reste de ce cours.

Remarque : La mémoire reste allouée même lorsque tous les processus qui y accèdent se
terminent : (le même problème que pour les autres IPC, la mémoire partagée doit donc être
libérée explicitement).

Asma Najjar -1- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

II.1 Création et accès à une zone mémoire

#include <sys/shm.h>

int shmget(key_t key,int size,int flags)

La fonction shmget permet la création d'une zone mémoire partagée, ou l'accès à une zone
déjà existante. . Elle retourne l'identifiant du segment ayant la clé key. Les drapeaux (flags)
permettent de spécifier les modalités d'ouverture, et notamment les droits de lecture et
d'écriture.

- key : clé de type key_t (défini dans /usr/include/sys/ipc.h, équivalent à long). Cette clé peut
être fixe ou créer par la fonction ftok ou prend la valeur IPC_PRIVATE dans le cas ou les
processus qui partage la mémoire partagé ont une relation de parenté.

- size : la taille du segment en octets.

- flags: combinaison, avec l'opérateur | , de droits d'accès et de constantes prédéfinies.


- Les droits d’accès

U G O
R 0400 0040 0004
W 0200 0020 0002

- Les constantes :
o IPC_CREAT: pour créer un nouveau segment. Sinon shmget() recherchera le
segment associé à clé, vérifiera que l'appelant a la permission de recevoir
l'identifiant shmid associé au segment, et contrôlera que le segment n'est pas
détruit.
o IPC_EXCL est utilisé avec IPC_CREAT pour garantir l'échec si le segment
existe déjà.

si key = IPC_PRIVATE
un nouveau segment est créé
sinon
si key ne correspond pas à un segment existant
si IPC_CREAT et IPC_EXCL ne sont pas positionné
Erreur et retour de -1
sinon
Un nouveau segment est créé et associé à cette clé avec
les droits d'accès mentionnés.
fsi
sinon
si IPC_CREAT et IPC_EXCL sont positionnés
Erreur et retour de -1
sinon
La fonction retourne l'identificateur du segment.
fsi
fsi
fsi

Asma Najjar -2- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

Exemple de création d'un segment de mémoire partagé


#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>

main ()
{
int num;

if ((num = shmget (IPC_PRIVATE, 1024, IPC_CREAT | IPC_EXCL | 0666)) == -1)


printf ("erreur\n") ;
else
printf ("segment d'identificateur %d créé\n", num);
}

II.2 Attachement d’un segment de mémoire


#include <sys/shm.h>

void *shmat (int id, char *addr, int flg)

Permet d'attacher la mémoire référencée à l'adresse virtuelle spécifiée en argument.


Le résultat est l'adresse à laquelle le système a effectivement réalisé l'attachement ou NULL
en cas d’erreur.

- id: identificateur du segment (la valeur de retour de la fonction shmget)

- addr: le choix du paramètre adrr est délicat. Il faut en effet respecter un certain nombre de
conditions, variables d'une machine à l'autre: l'alignement, la plage d'adresses autorisées aux
segments de mémoire partagée, les adresses de pages virtuelles et physiques etc... On utilisera
de préférence adrr = NULL, c'est-à-dire qu'on laisse le soin au système de sélectionner
l'adresse. Si l'on veut quand même positionner le segment dans une certaine zone de l'espace
d'adressage, on utilise l'indicateur SHM_RND dans le paramètre flg pour que le système
choisisse une adresse valable la plus proche possible de adrr.

- flg :
- SHM_RND : voir ci-dessus.
- SHM_RDONLY : si cette constante est placée, l’attachement se fera en lecture seul.
Si non le segment de mémoire pourra être utilisé en lecture et écriture.

II.3 Détachement d’une zone mémoire


#include <sys/shm.h>

int shmdt (char *addr)

Permet le détachement d'un segment de mémoire partagée de l'espace virtuel du processus. La


fonction shmdt ne détruit pas le segment de mémoire. Seul un appel à shmctl peut le faire.
Elle retourne 0 en cas de succès et - 1 en cas d'échec.

Asma Najjar -3- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

- adrr: adresse d’attachement du segment: valeur retournée par la fonction shmat.

II.4 Contrôle d’une zone mémoire

#include <sys/shm.h>

int shmctl(int id, int cmd, struct shmid_ds *buf);

Permet de consulter ou de modifier les caractéristiques d'un segment mémoire ainsi que de
le supprimer. Elle retourne 0 en cas de succès et- 1 en cas d'erreur, avec :

- id : identificateur du segment. La valeur de retour de la fonction shmget.


- buf : pointeur sur la structure shmid_ds, contenant une copie des informations sur le
segment.
struct shmid_ds {
struct ipc_perm shm_perm; /*Droits d'accès*/
int shm_segsz; /*Taille du segment*/
time_t shm_atime; /*Moment du dernier attachement*/
time_t shm_dtime; /*Moment du dernier détachement*/
time_t shm_ctime; /*Moment du dernier changement*/
pid_t shm_cpid; /*PID du dernier attachement*/
pid_t shm_lpid; /*PID du dernier détachement*/
short shm_nattch; /*Nombre d'attachement. */
};

struct ipc_perm {
key_t key; /* Clé fournie à msgget */
uid_t uid; /* UID effectif du propriétaire */
gid_t gid; /* GID effectif du propriétaire */
uid_t cuid; /* UID effectif du créateur */
gid_t cgid; /* GID effectif du créateur */
unsigned short mode; /* Permissions */
unsigned short seq; /* Numéro de séquence */
};

- cmd:
 IPC_STAT : la structure shmid_ds associée au segment est copiée dans la structure
pointée par buf.
 IPC_SET : la structure shmid_ds associée au segment est modifiée par les valeurs des
champs de la structure pointée par buf.
 IPC_RMID : suppression du segment de la mémoire. La suppression sera différée si le
segment est encore attaché à un processus.

Asma Najjar -4- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

Exemple 1
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define CLEF 12347


int main(void) {
int *zone;
int memid;
/* création ou lien avec une zone partagée */
memid = shmget(CLEF, 100, 0600 | IPC_CREAT | IPC_EXCL);
if (memid == -1) { perror("shmget"); return (EXIT_FAILURE); }
/* montage en mémoire */
zone = shmat(memid, NULL, 0);
/* utilisation */
printf("zone[0] = %d\n", zone[0]++ );
return (EXIT_SUCCESS);

Exemple 2: Un producteur et un consommateur

Le producteur
1 /* prod.c */
2 /*
3 Ce programme lit une suite de nombres, et effectue le cumul dans
4 une variable en mémoire partagée.
*/

5 #include <sys/ipc.h>
6 #include <sys/shm.h>
7 #include <sys/types.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <errno.h>

11 void abandon(char message[])


12 {
13 perror(message);
14 exit(EXIT_FAILURE);
15 }

16 struct donnees {
17 int nb;
18 int total;
19 };

20 int main(void)
21 {
22 key_t cle;
23 int id;
24 struct donnees *commun;
25 int reponse;

Asma Najjar -5- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

26 cle = ftok(getenv("HOME"), 'A');


27 if (cle == -1)
28 abandon("ftok");

29 id = shmget(cle, sizeof(struct donnees),


30 IPC_CREAT | IPC_EXCL | 0666);
31 if (id == -1) {
32 switch (errno) {
33 case EEXIST:
34 abandon("Note: le segment existe déjà\n");
35 default:
36 abandon("shmget");
37 }
38 }
39 commun = (struct donnees *) shmat(id, NULL, SHM_R | SHM_W);
40 if (commun == NULL)
41 abandon("shmat");

42 commun->nb = 0;
43 commun->total = 0;

44 while (1) {
45 printf("+ ");
46 if (scanf("%d", &reponse) != 1)
47 break;
48 commun->nb++;
49 commun->total += reponse;
50 printf("sous-total %d= %d\n", commun->nb, commun->total);
51 }
52 printf("---\n");

53 if (shmdt((char *) commun) == -1)


54 abandon("shmdt");

55 /* suppression segment */
56 if (shmctl(id, IPC_RMID, NULL) == -1)
57 abandon("shmctl(remove)");

58 return EXIT_SUCCESS;
59 }

Le consommateur
1 /* cons.c */
2 /*
3 Ce programme affiche périodiquement le contenu de la
4 mémoire partagée. Arrêt par Contrôle-C
5 */

6 #include <sys/ipc.h>
7 #include <sys/shm.h>
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <errno.h>
13 #include <signal.h>

14 #define DELAI 2

Asma Najjar -6- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

15 void abandon(char message[])


16 {
17 perror(message);
18 exit(EXIT_FAILURE);
19 }

20 struct donnees {
21 int nb;
22 int total;
23 };

24 int continuer_boucle = 1;

25 void arreter_boucle(int signal)


26 {
27 continuer_boucle = 0;
28 }

29 int main(void)
30 {
31 key_t cle;
32 int id;
33 struct donnees *commun;
34 struct sigaction a;

35 cle = ftok(getenv("HOME"), 'A');


36 if (cle == -1)
37 abandon("ftok");

38 id = shmget(cle, sizeof(struct donnees), 0);


39 if (id == -1) {
40 switch (errno) {
41 case ENOENT:
42 abandon("pas de segment\n");
43 default:
44 abandon("shmget");
45 }
46 }

47 commun = (struct donnees *) shmat(id, NULL, SHM_R);


48 if (commun == NULL)
49 abandon("shmat");

50 continuer_boucle = 1;

51 a.sa_handler = arreter_boucle;
52 sigemptyset(&a.sa_mask);
53 a.sa_flags = 0;
54 sigaction(SIGINT, &a, NULL);

55 while (continuer_boucle) {
56 sleep(DELAI);
57 printf("sous-total %d= %d\n", commun->nb, commun->total);
58 }

59 printf("---\n");
60 if (shmdt((char *) commun) == -1)
61 abandon("shmdt");
62 return EXIT_SUCCESS;
63 }

Asma Najjar -7- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

III- Les sémaphores

III.1 Principe générale


Le concept de sémaphore a été introduit par Dijkstra en 1965. Un sémaphore S est une
variable à valeurs entières non négatives sur lesquelles on peut effectuer les deux opérations
atomiques P et V suivantes :

 Opération P(S)
si S > 0 alors
S=S-1
sinon
Bloquer le processus en le plaçant dans une file associée à S.
finsi

Opération V(S)
S=S+1;
si la file associée à S n'est pas vide alors
Débloquer (au moins) un processus de la file.
finsi

III.2 Les sémaphores sous Unis

L’implantation des sémaphores sous Unix est beaucoup plus riche que la simple
implémentation des opérations P et V. En effet, les opérations Pn et Vn sont implémentées.
Elles permettent d’obtenir ou de libérer n occurrences de la ressource et ceci de manière
atomique.
Unix implémente les ensembles de sémaphores. Un processus peut obtenir ou libérer n
occurrences de la ressource R1 et m occurrences de la ressource R2. Cette implémentation
propose également une nouvelle opération appelée Z qui attend qu’un sémaphore devienne
nul.

Opération Pn(S)
si S ≥ n alors
S=S-n
sinon
Bloquer le processus en le plaçant dans une file associée à S.
finsi

Opération Vm(S)
S=S+m;
si la file associée à S n'est pas vide alors
Débloquer (au moins) un processus de la file.
Finsi

Opération Z
Bloquer le processus jusqu'à ce que S=0.

Asma Najjar -8- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

III.2.1 Création d’un ensemble de sémaphores

La fonction qui permet la création ou la récupération d’un ensemble de sémaphores est la


suivante :
#include <sys/sem.h>

int semget (key_t key, int nb_sem, int flags);

- key : clé de type key_t (défini dans /usr/include/sys/ipc.h, équivalent à long). Cette clé
peut être fixe ou créer par la fonction ftok ou prend la valeur IPC_PRIVATE dans le cas
ou les processus qui partage l’ensemble de sémaphores ont une relation de parenté.

- nb_sem: Nombre de sémaphore dans l’ensemble.

- flags:Indications des droits d’accès et utilisation des indicateurs IPC_CREAT et


IPC_EXCL pour la création.

En cas de succès, la valeur de retour de cette fonction est l'identifiant d'un ensemble de sémaphores.
Cet ensemble contient nb_sem sémaphores numérotés de 0 à nb_sem-1. Pour spécifier un
sémaphore parmi les nb_sem, l'utilisateur indique l'identificateur de l’ensemble (id) et le
numéro du sémaphore.
A chaque ensemble de sémaphore sont associés des droits d'accès. Ces droits sont nécessaires
pour effectuer des opérations sur les sémaphores, mais non inopérants pour :
- La destruction d'un identificateur de sémaphore,
- La modification des droits d'accès.
Seuls le créateur, le propriétaire ou le super-utilisateur peuvent réaliser ces opérations.

III.2.2 Opérations sur un ensemble de sémaphores

Chacune des opérations Pn, Vm et Z sur un sémaphore est décrite grâce à la structure sembuf
et la fonction semop.

La fonction semop

#include <sys/sem.h>

int semop (int id, struct sembuf *tab, int nbre);

- id: L’identificateur de l’ensemble de sémaphores: la valeur de retour de la fonction la


fonction semget.

- tab: Le tableau indiquant les opérations à effectuer sur chaque sémaphore de l’ensemble.
Chaque case est de type sembuf.

- nbre: Le nombre des opérations de ce tableau à prendre en compte.

Remarque: L’ensemble des opérations est réalisé atomiquement. Si une opération ne peut être
réalisée, alors aucune opération n’est effectuée et le processus est mis en sommeil.

Asma Najjar -9- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

 La structure sembuf

struct sembuf {
ushort sem_num; /* numéro du sémaphore dans l’ensemble*/
short sem_op; /* opération sur le sémaphore */
short sem_flg; /* option */
};

- L’attribut sem_num correspond au numéro du sémaphore dans l’ensemble. La numérotation


commence à 0.

- L’attribut sem_op détermine la nature de l’opération

 Si sem_op > 0 : opération Vm. La valeur du sémaphore est augmentée de sem_op. Au


plus sem_op processus en attente sur le sémaphore sont réveillés.

 Si sem_op < 0 : opération Pn. La valeur absolue est retranchée de la valeur du


sémaphore. Si le résultat est nul tous les processus en attente de cet événement sont
réveillés, si non, si elle est négative le processus est mis en attente d'une augmentation
de la valeur du sémaphore.

 sem_op = 0 : opération Z. Si le sémaphore n’est pas nul, alors le processus est bloqué.

- L’attribut sem_flg représente une conjonction des options possibles. Parmi les options
suivantes :

 IPC_NOWAIT : qui rend l’opération non bloquante,


 SEM_UNDO : qui annule l’effet de l’opération en cas de terminaison intempestive du
processus.

III.2.3 Fonction de contrôle sur un ensemble de sémaphore

La fonction de contrôle sur un ou plusieurs sémaphores d’un ensemble est la suivante :

#include <sys/sem.h>

int semctl (int id, int semnum, int op , arg);

- id : est l'identificateur de l'ensemble de sémaphores concerné: la valeur de retour de la


fonction semget.
- semnum : est le n° du sémaphore dans l'ensemble.
- op: désigne l’opération à effectuer. Elle peut prendre l’une des valeurs suivantes:

- GETVAL : retourne la valeur du sémaphore de numéro semnum.


- SETVAL : le sémaphore de numéro semnum reçoit la valeur de arg.
- GETPID: retourne le PID du processus qui est intervenu en dernier lieu.
- GETNCNT: retourne le nombre de processus en attente d'une incrémentation de la
valeur du sémaphore de numéro semnum
- GETZCNT : retourne le nombre de processus en attente du passage à 0 du sémaphore
ayant comme numéro semnum
- GETALL : range les valeurs de tous les sémaphores dans le tableau pointé par
arg.array

Asma Najjar -10- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

- SETALL : les semnum premiers sémaphores de l’ensemble semid sont initialisés


selon le contenu du tableau arg.array
- IPC_STAT : la structure (doit être passé en paramètre) associée à semid est rangée à
l'adresse contenue dans arg.buf.
- IPC_SET : positionne les valeurs gid, uid et mode à partir de la structure pointée par
arg.buf (arg doit être passée en paramètre)
- IPC_RMID : l’ensemble de sémaphores identifié par id est supprimé.

Récapitulation: la valeur de du paramètre arg dépend de l’opération à effectuer. Ce


paramètre peut ne pas être présent.

Remarque : Le quatrième argument, s’il est présent, et une union semun devant posséder les
arguments suivants :
union semun
{
int val;
struct semid_ds *buf;
ushort * array;
}arg;

struct semid_ds {
struct ipc_perm sem_perm; /* permissions .. see ipc.h */
time_t sem_otime; /* last semop time */
time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
struct wait_queue *eventn;
struct wait_queue *eventz;
struct sem_undo *undo; /* undo requests on this array */
ushort sem_nsems; /* no. of semaphores in array */
};

Asma Najjar -11- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

Exemple

1 /* sem.c */

2 /*
3 Opérations sur des sémaphores
4 */

5 #include <sys/types.h>
6 #include <sys/ipc.h>
7 #include <sys/sem.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <ctype.h>

12 typedef int SEMAPHORE;

13 void abandon(char message[])


14 {
15 perror(message);
16 exit(EXIT_FAILURE);
17 }

18 void detruire_sem(SEMAPHORE sem)


19 {
20 if (semctl(sem, 0, IPC_RMID, 0) != 0)
21 abandon("detruire_sem");
22 }

23 void changer_sem(SEMAPHORE sem, int val)


24 {
25 struct sembuf sb[1];
26 sb[0].sem_num = 0;
27 sb[0].sem_op = val;
28 sb[0].sem_flg = 0;
29 if (semop(sem, sb, 1) != 0)
30 abandon("changer_sem");
31 }

32 SEMAPHORE creer_sem(key_t key)


33 {
34 SEMAPHORE sem;
35 int r;

36 sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);


37 if (sem < 0) {
38 perror("creer_sem");
39 exit(EXIT_FAILURE);
40 }
41 r = semctl(sem, 0, SETVAL, 3); /* valeur initiale = 3 */
42 if (r < 0) {
43 perror("initialisation sémaphore");
44 exit(EXIT_FAILURE);
45 }
46 return sem;
47 }

48 void P(SEMAPHORE sem)


49 {
50 changer_sem(sem, -1);

Asma Najjar -12- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

51 }

52 void V(SEMAPHORE sem)


53 {
54 changer_sem(sem, 1);
55 }

56 /* --------------------------------------------- */

57 int main(int argc, char *argv[])


58 {
59 SEMAPHORE sem;
60 key_t key;
61 int encore = 1;

62 if (argc != 2) {
63 fprintf(stderr, "Usage: %s cle\n", argv[0]);
64 abandon("Mauvais nombre de paramètres");
65 }
66 key = atoi(argv[1]);
67 sem = creer_sem(key);
68 while (encore) {
69 char reponse;
70 printf("p,v,x,q ? ");
71 if (scanf("%c", &reponse) != 1)
72 break;
73 switch (toupper(reponse)) {
74 case 'P':
75 P(sem);
76 printf("OK.\n");
77 break;
78 case 'V':
79 V(sem);
80 printf("OK.\n");
81 break;
82 case 'X':
83 detruire_sem(sem);
84 printf("Sémaphore détruit\n");
85 encore = 0;
86 break;
87 case 'Q':
88 encore = 0;
89 break;
90 default:
91 printf("?\n");
92 }
93 }
94 printf("Bye.\n");
95 return EXIT_SUCCESS;
96 }

Asma Najjar -13- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

IV- les fils de messages

IV-1 Présentation générale

Il s'agit d'une implémentation du concept de boite à lettres. Le but est d'échanger, de façon
asynchrone, des messages. Chaque message possède un corps de longueur variable, et un
type qui peut servir à préciser la nature des informations contenues dans le corps. Au moment
de la réception d'un message, on peut choisir de sélectionner les messages d'un type donné.

Le corps doit être déclaré et défini comme suit :

struct msgbuf {
long mtype; /* type du message, doit être >0 */
char mtest[TAILLE_MAX_DES_MESSAGE] /* les données du message */
};

Le premier attribut de la structure msgbuf doit obligatoirement être de type long. Le corps
de message peut être de n’importe quel type (dans l’exemple ci dessus, on a une chaine de
caractère).
Les messages sont rangés dans une file de messages qui est une zone de mémoire centrale
gérée par le système. Le processus qui a créé une file de messages en est le propriétaire.
Une file de messages est associée à une clé utilisée pour obtenir l'identificateur de la file de
messages (id).
Tout processus qui a connaissance de l'existence de la file de messages et qui possède des
droits d'accès peut réaliser des opérations sur la file :
- Création d'une file,
- Consultation des caractéristiques d'une file :
- Envoi d'un message dans la file,
- Lecture (extraction) d'un message, en liaison avec son type.

IV.2 Création d’une file de message


#include <sys/ipc.h>
#include <sys/msg.h>

int msgget (key_t key, int flags)

Cette fonction permet la création ou la récupération d’une file de messages. Elle retourne
l'indicateur de la file (ou -1 en cas d'erreur).

- key : clé de type key_t (défini dans /usr/include/sys/ipc.h, équivalent à long). Cette clé
peut être fixe ou créer par la fonction ftok ou prend la valeur IPC_PRIVATE dans le cas
ou les processus qui partage la file de message ont une relation de parenté.
- flags : combinaison, avec l'opérateur | de droits d'accès et de constantes.

- MSG_R (0400), MSG_W (0200): permission en lecture, en écriture


- IPC_CREAT: création d'une nouvelle file de messages.
- IPC_EXCL : échec si la file existe déjà

Asma Najjar -14- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

Exemple
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

main ()
{
key_t cle;
int flag, num, i;
printf ("donnez la cle entière associée à la file à créer : ");
scanf ("%ld", &cle);
flag = MSG_W | MSG_R | IPC_CREAT | IPC_EXCL;
/* autre solution : flag = IPC_CREAT | IPC_EXCL | 0666 ; */

if ((num = msgget (cle, flag)) == -1)


/* autre solution : if (((num = msgget (ftok (CHEMIN, cle), flag)) == -1)*/
{
fprintf (stderr, "création impossible\n");
exit (1);
}
printf ("file créée avec l'identificateur %d\n", num);
}

IV.3 Opération de contrôle sur une file de message


int msgctl (int id, int cmd, struct msqid_ds *buf)

Cette primitive permet la consultation et la modification des caractéristiques d’une file de


messages. Retourne 0 en cas de succès et -1 en cas d'échec.

- id : identificateur de la file

- cmd : définit les opérations à effectuer, selon sa valeur :


- IPC_RMID : la file est supprimée.
- IPC_SET : mise à jour de quelques valeurs de permission (champs de la structure
msg_perm (attribut de la structure buf) associée à msgid : msg_perm.uid,
msg_perm.gid et msg_perm.mode).
- IPC_STAT : recopie dans buf les informations relatives à la file contenues dans
l'objet de type struct msqid_ds, associé à la file.

- buf est un pointeur sur une structure de type msqid_ds. Elle contient une copie des
informations représentant la file de messages.

struct msqid_ds {
struct ipc_perm msg_perm; /* Appartenance et permissions */
time_t msg_stime; /* Heure du dernier msgsnd */
time_t msg_rtime; /* Heure du dernier msgrcv */
time_t msg_ctime; /* Heure de la dernière modification */
unsigned long __msg_cbytes; /* Nombre actuel d'octets dans la file */
msgqnum_t msg_qnum; /* Nombre actuel de messages dans la file */
msglen_t msg_qbytes; /* Nombre maximum d'octets aurisés dans la file */
pid_t msg_lspid; /* PID du dernier msgsnd(2) */
pid_t msg_lrpid; /* PID du dernier msgrcv(2) */
};

Asma Najjar -15- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

IV.4 Ecriture d’un message dans la file de message

int msgsnd (int id, struct msgtxt *msgp, int msgz, int msgflg)

Cette primitive permet l’envoie un message dans la file d’identifiant id. Le corps de ce
message contient msgsz octets, il est placé, précédé par le type dans le tampon pointé par
msgp. Retourne 0 en cas de succès -1 en cas d'erreur, avec :

- id : identificateur de la file. La valeur retournée par la fonction msgget.

- Le paramètre msgp doit être un pointeur sur une structure de la forme suivante :

struct msgbuf
{
long mtype; /* type du message */
char mtext […]; /* contenu du message */
};

- msgz : taille réelle du message.

- msgflg : ce paramètre peut prendre les valeurs :


- 0 : blocage de la fonction si la file est pleine
- IPC_NOWAIT : si la file est pleine, l'appel à la fonction n'est pas bloquant.

IV.5 Lecture d’un message de la file


int msgrcv (int id, struct msgtxt *buf, int msgz, long msgtype, int msgflg)

La primitive msgrcv lit dans la file un message d'un type donné (si msgtype > 0) ou
indifférent (si msgtype==0), et le place dans le tampon pointé par msgtxt. La taille du corps
ne pourra excéder msgsz octets, sinon il sera tronqué. Elle renvoie la taille du corps du
message et -1 en cas d’erreur.

- id : identificateur de la file
- msgz : taille maximale d'un message recevable.
- msgtype: Le type du message à extraire :
- si msgtype=0: le premier message dans la file, quelque soit son type.
- si msgtype > 0: le premier message de type msgtyp dans la file.
- si msgtype < 0: le premier message de type 0 ... |msgtyp|.

- msgflg: précise l'action à réaliser si aucun message du type attendu n'est présent dans la
file :
-Si IPC_NOWAIT est positionné, on retourne -1 et l'appel est non bloquant.
-Sinon, la fonction se bloque jusqu'à l'arrivée d'un message satisfaisant ou jusqu'à
réception d'un signal par le processus appelant ou jusqu'à disparition de la file.

Asma Najjar -16- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

Exemple

Emetteur
1 /* snd.c */
2 /*
3 envoi des messages dans une file (IPC System V)
4 */

5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdio.h>

9 #include <sys/types.h>
10 #include <sys/ipc.h>
11 #include <sys/msg.h>

12 #define MAX_TEXTE 1000

13 struct tampon {
14 long mtype;
15 char mtext[MAX_TEXTE];
16 };

17 void abandon(char message[])


18 {
19 perror(message);
20 exit(EXIT_FAILURE);
21 }

22 int main(int argc, char *argv[])


23 {
24 int cle, id, mtype;
25 if (argc != 3) {
26 fprintf(stderr, "Usage: %s clé type\n", argv[0]);
27 abandon("mauvais nombre de paramètres");
28 }
29 cle = atoi(argv[1]);
30 mtype = atoi(argv[2]);
31 id = msgget(cle, 0666);
32 if (id == -1)
33 abandon("msgget");

34 while (1) {
35 struct tampon msg;
36 int l, r;

37 printf("> ");
38 fgets(msg.mtext, MAX_TEXTE, stdin);
39 l = strlen(msg.mtext);
40 msg.mtype = mtype;
41 r = msgsnd(id, (struct msgbuf *) &msg, l + 1, 0);
42 if (r == -1)
43 abandon("msgsnd");
44 }
45 }

Asma Najjar -17- Chapitre 4


Programmation système sous unix 2ème ING-ISI (2011-2012)

 Récepteur
1 /* rcv.c */

2 /*
3 affiche les messages qui proviennent
4 d'une file (IPC System V)
5 */

6 #include <errno.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdio.h>

10 #include <sys/types.h>
11 #include <sys/ipc.h>
12 #include <sys/msg.h>

13 #define MAX_TEXTE 1000


14 struct tampon {
15 long mtype;
16 char mtext[MAX_TEXTE];
17 };

18 int continuer_boucle = 1;

19 void abandon(char message[])


20 {
21 perror(message);
22 exit(EXIT_FAILURE);
23 }

24 int main(int argc, char *argv[])


25 {
26 int cle, id;
27 if (argc != 2) {
28 fprintf(stderr, "Usage: %s cle\n", argv[0]);
29 abandon("Mauvais nombnre de paramètres");
30 }
31 cle = atoi(argv[1]);
32 id = msgget(cle, IPC_CREAT | 0666);
33 if (id == -1)
34 abandon("msgget");

35 while (continuer_boucle) {
36 struct tampon msg;
37 int l = msgrcv(id, (struct msgbuf *) &msg, MAX_TEXTE, 0L,
0);
38 if (l == -1)
39 abandon("msgrcv");
40 printf("(type=%ld) %s\n", msg.mtype, msg.mtext);
41 }

42 return EXIT_SUCCESS;
43 }

Asma Najjar -18- Chapitre 4

Vous aimerez peut-être aussi