You are on page 1of 51

Linux Principes et Programmation

3. Communication inter-processus Tubes, IPC, MSQ, SHM


CNAM NSY103 2009/2010 Yann GAUTHERON

Extraits : http://fr.wikipedia.org/, LINUX Programmation systme et rseau (Jolle DELACROIX), Unix: communications internes (C. Crochepeyre) http://www.cnam.fr/

Communication interne UNIX

Communication Interne

exec() Fichiers Signaux Tubes Doors (Solaris) IPC : Communication Inter Processus

MSQ : Files de messages SHM : Mmoire partage

Communication Externe

Sockets Moyens divers et varis pour changes de donnes avec d'autres machines

Communication interne UNIX

exec()

Commande Unix sous Shell et main() /usr/bin/ # prog a b c main(argc, argv, anvp) Paramtres dappel

l'excution de main(argc, argv, envp) on rcupre


argc : le nombre de paramtres du 2me paramtre argv : l'adresse d'un tableau dadresses de chanes de caractres sous Unix la premire chane est le nom du programme (prog) envp : l'adresse dun tableau dadresses de chanes de caractres donnant les valeurs des variables Shell

Communication interne UNIX

exec()

Interface

main(argc, argv, envp) int argc; char **argv, **envp;

argc : nombre dlments du tableau dadresses point par argv argv : pointe sur le tableau qui contient les adresses des paramtres dappel envp : pointe sur le tableau qui contient les adresses des variables denvironnement

Communication interne UNIX

exec()

Exemple dappel:

/usr/bin/ # prog par1 par2 par3 par4 avec variables denvironnement: TERM = vt100 HOME=/usr/moi

La commande est compose de 5 paramtres main(argc, argv, envp) aprs excution argc = 5 argv = adresse tableau contenant [prog par1 par2 par3 par4] envp = adresse tableau contenant [TERM=vt100 HOME=/usr/moi]

Communication interne UNIX


- Exemple de programme C
Affichage des paramtres d'appel du programme lui-mme : main(int argc, char **argv, char **envp) { int k; for(k=0;k<argc;++k) { printf("paramtres %d: %\n",k+1,argv[k]); argv[k]; } for(k=0;;++k) { if (envp[k][0]) printf("environnement %d: %\n",k+1,envp[k]); else break; } exit(0); }

Communication interne UNIX


- La variable d'environnement Unix : environ
La variable 'environ' sous Unix est un pointeur sur un tableau de pointeurs vers les chanes de caractres des variables d'environnement. Exemple : extern char **environ; main(){ int k; for(k=0;;++k) { if(environ[k][0]) printf("environnement %d: %\n",k+1,environ[k]); else break; } exit(0); }

Communication interne UNIX

Les tubes ou PIPE

Deux types :

tube anonyme tube nomm

Moyen de communication entre deux processus sexcutant sur une mme machine Fichiers particuliers (SGF) Grs par le noyau File de donnes en mmoire (FIFO) Lectures destructrices

Les Tubes

Les tubes anonymes

Structure sans nom Communication entre deux processus Deux descripteurs: lecture et criture Deux pointeurs automatiques: lecture et criture

pointeur de lecture sur le 1er caractre non lu pointeur dcriture sur le 1er emplacement vide

Processus de mme filiation

Les Tubes

Les tubes anonymes

Les Tubes

Les tubes anonymes

Principe de base pre-fils


pipe(): cration du tube par le pre fork(): cration du processus fils

hritage de louverture du tube (fichier) exec()

Passage des descripteurs en paramtres

Les Tubes

Les Tubes

Les tubes anonymes

Les Tubes

Les tubes anonymes : caractristiques

Louverture du tube se fait par pipe() et non open() lseek() interdit taille limite / taille du tampon allou descripteurs de lecture ferms et tentative dcriture

signal SIGPIPE arrt du processus le 1er qui lit rcupre les donnes

lectures multiples:

Les Tubes

Les tubes anonymes : anomalies possibles

(tube vide) && (lecture)


code erreur = 0 processus bloqu jusqu dpt de donnes code erreur = 0 processus bloqu jusqu dpt de donnes code erreur = 0 processus bloqu jusqu lecture de donnes

(tube non vide) && (nombre de donnes lire > donnes existantes)

(tube plein) && (criture)


Linux source : x86: /include/linux/limits.h:13 #define PIPE_BUF 4096 Arm: include/asm-arm/limits.h:8: #define PIPE_BUF PAGE_SIZE

Les Tubes

Les tubes anonymes : synchronisation

Les Tubes

Les tubes anonymes : synchronisation

PA transmet PB ou PB transmet PA

PA dpose et PA lit => PB bloqu PA et PB dposent et PB lit => risque que PB lise sa propre donne

Les Tubes

Les tubes anonymes : synchronisation

Modle Question/Rponse : Fermeture des descripteurs inutiles

Les Tubes

Les tubes anonymes : Fonction tube

pipe (tab)

cre un tube retourne les ndes deux descripteurs dans un tableau tab tab[0]: ndu descripteur de lecture: dl tab[1]: ndu descripteur dcriture: de remplit la fonction douverture dun fichier classique

Les Tubes

Les tubes anonymes : Exemple

#include<stdio.h> Int pip[2];/* descripteur de pipe */ char buf[6]; main() { pipe(pip); /* cration pipe */ switch(fork()){ case -1: perror("pipe"); exit(1); case 0: fils(); default: pere(); } pere() {write(pip[1],hello,5); exit(0);}/* criture pipe */ fils() {read(pip[0],buf,5); exit(0);}/* lecture pipe */ }

Les Tubes

Les tubes anonymes : dup()

Les Tubes

Utilisation de dup() pour rediriger vers la sortie standard

On cre un tube :

Les descripteurs 3 et 4 pointent vers la table des fichiers (ici le tube) 1 est libre 4 recopi dans 1 Valeur de retour == nouveau descripteur, ici 1

On ferme le 1

On duplique le 4 avec retour = dup(4)


On ferme 3 et 4 qui ne servent plus Tout envoi vers 1 concernera le tube

Les Tubes

Les tubes nomms

Caractristiques communes aux tubes anonymes :


communication entre processus sexcutant sur une mme machine fichier particulier file de messages en mmoire pointeurs grs automatiquement: lseek() inutilisable fichier portant un nom filiation non ncessaire cration par la fonction SGF mknod() ouverture par open() un seul descripteur par ouverture de tube fichier persistant

Diffrences :

Les Tubes

Les tubes nomms : synchronisation

Les Tubes

Les tubes nomms

Fonction cration SGF


mknod(nom,mode|S_FIFO) mkfifo(nom,mode)

Passage des descripteurs en paramtres


utilisation de la fonction de cration dun inode particulier spcifier un nom de fichier donner les droits daccs cration dun fichier fonctionnant en mode FIFO

Les Tubes

Les tubes nomms

desc= open(nom_du_fichier, mode)


ouverture en lecture si mode = O_RDONLY ouverture en criture si mode = O_WRONLY ouverture en maj si mode = O_RDWR ouverture bloquante / non bloquante mode = O_NDELAY

Les Tubes

Les tubes nomms

read(desc, buf, nb)lecture dans le tube

si O_NDELAY l'ouverture retour code erreur si lecture dans un tube vide sinon

processus bloqu si tube vide, attente tube suffisamment de donnes lire write(desc, buf, nb)criture dans le tube

si O_NDELAY l'ouverture retour code erreur si tube plein sinon


processus bloqu si tube plein, attente tube suffisamment vide pour crire

Les Tubes

Les tubes nomms

close(desc)

fermeture du descripteur du fichier ouvert dans chacun des processus destruction du fichier commande shell de destruction du fichier

Ou unlink(nom_du_fichier)

Ou rm nom_du_fichier

Les Tubes

Exemple d'utilisation des tubes nomms

/* Processus ecrivain */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> main() { mode_t mode; int tub; mode = S_IRUSR | S_IWUSR; /* cration fichier FIFO */ mkfifo("fictub",mode) /* ouverture fichier */ tub = open("fictub",O_WRONLY) /* criture dans fichier */ write(tub,"0123456789",10); close(tub); exit(0);

Les Tubes

Exemple d'utilisation des tubes nomms

/* Processus lecteur */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> main() { int tub; char buf[11]; /* ouverture fichier */ tub = open("fictub",O_RDONLY); /* lecture du fichier */ read(tub,buf,10); buf[11]=0; printf("J'ai lu %s\n", buf); close(tub); exit(0);

Communication interne UNIX

Les IPCs

Externe au SGF Identification et manipulation par une cl Interface commun aux IPCs :

/usr/include/sys/ipc.h /usr/include/sys/types.h Files de messages Mmoire partage Smaphores ipcs : voir un IPC ipcrm : supprimer un IPC

Les IPCs :

Commandes :

Les IPCs
Fichier types.h dfinitions des types /machine Fichier ipc.h
type def long mtyp_t; /* ipc type message */ struct ipc_perm { uid_t uid /* gid_t gid /* uid_t cuid /* gid_t uguid /* mode_t mode /* ushort_t seq key_t key; /* } identification du identification du identification du identification du mode daccs */ cl*/ propritaire */ groupe */ crateur */ groupe la cration */

Les IPCs

Modes

00400 lecture par utilisateur 00200 criture par utilisateur 00040 lecture par groupe 00020 criture par groupe 00004 lecture par les autres 00002 criture par les autres

Variable Symbolique

IPC_ALLOC IPC_CREAT IPC_EXCL

0100000 0001000 0002000

/* indicateur objet allou */ /* cration si cl nexiste pas */ /* chec si cl existe */ /* erreur en cas dattente */

IPC_NOWAIT 0004000

Les IPCs

Identifiant unique de type key_t

Cl unique utile pour accder une ressource depuis plusieurs processus Valeur numrique pouvant exister de deux manires :

Fige dans le code source

Calcule par le systme partir d'une rfrence commune : un nom de fichier est un entier key_t ftok (const char *ref, int numero); Commande ipcs pour visualiser toutes les IPCs d'un systme

Les IPCs

Les files de messages ou MSQ

File de messages : mode FIFO particulier Identificateur MSQ : entier fourni par le systme la cration

msqid (similaire un nde descripteur) dposs par un ou plusieurs processus relus par un ou plusieurs processus

Ensemble de messages typs


aucune filiation exige lecture destructrice structure associe : fichier msg.h

Les IPCs

Les files de messages ou MSQ

Les IPCs

Les files de messages ou MSQ

Accs aux files via msgget()


Cration d'une nouvelle file de messages Accs une file dj existante

Prototype : int msgget(key_t cle, int option) Retourne l'identifiant de la file si tout s'est bien pass, sinon errno est :

EACCESS : Problme de droits EEXIST : une IPC existe dj ce numro EIDRM : IPC dtruite ENOENT : IPC inconnue (et cration non demande) ENOMEM : Table des IPCs sature ENFILE : Nombre maximal d'IPCs dpass

Environ MSGMNI files de messages maximum (dfaut = 128 x 4096oc)

Les IPCs

Mcanisme des files de messages

Cration :

Avec cl msgget(cle, IPC_CREAT | IPC_EXCL | 0660); Sans cl : accessible uniquement par les descendants

Utilisation de IPC_PRIVATE comme cl Rcupration d'un msqid :

msgget(cle, 0); int msgctl(int msqid, int op, struct msqid_ds *buf)

Contrle :

Destruction d'une MSQ : msgctl(cle, IPC_RMID, NULL); IPC_STAT lecture de la structure dans buf IPC_SET modification de la structure partir de buf

Les IPCs

Mcanisme des files de messages

criture :

int sgsnd( int idint ,const void *msg ,int longeur ,int option);

Cette fonction est bloquante, sauf si l'option IPC_NOWAIT est positionne.


Retourne 0 en cas de succs, sinon errno est :

EACESS : Problme de droits EINVAL : File n'existe pas ou type invalide EAGAIN : File pleine et IPC_NOWAIT non positionn EFAULT : Adresse invalide EIDRM : File dtruite EINTR : Le processus a reu un signal, l'appel systme a chou ENOMEM : La mmoire manque pour pouvoir copier l'objet

Les IPCs

Mcanisme des files de messages

Lecture :

int msgrcv(int idint,const void *msg ,int longeur,long le_type,int option);


le_type > 0 : retourne msg le + ancien dont type gal le_type le_type = 0 : retourne msg le + ancien (FIFO) le_type < 0 : retourne msg le + ancien du type minimum inf ou gal | le_type | EACESS : Problme de droits EINVAL : File n'existe pas ou type invalide E2BIG : Taille du message plus grande que celle spcifie (sans opt. MSG_NOERROR) EFAULT : Adresse invalide EIDRM : File dtruite EINTR : Le processus a reu un signal, l'appel systme a chou ENOMSG : L'option IPC_NOWAIT a t positionne et aucun message dans la file

Le paramtre le_type permet de dsigner un message extraire :


Retourne 0 en cas de succs, sinon errno est :


Le message est lu et dtruit.

Exemple d'utilisation des MSQ :

Les IPCs

/* Cration d'une MSQ et envoi message*/ #include <sys/types.h> #include <sys/ipc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define CLE 17 struct msgbuf{ long le_type; /* type du message */ char mtext[20]; /* texte du message */ }; main() { struct msgbuf msgp; char *msg="ceci est un message"; int msqid;

/* identificateur MSQ */ /* /* /* /* creation MSQ */ le type */ le message */ envoi message */

msqid=msgget((key_t)CLE,IPC_CREAT|0750); msgp.le_type=12; strcpy(msgp.mtext,msg); msgsnd(msqid, &msgp, strlen(msg), IPC_NOWAIT); exit(0);

Les IPCs

Exemple d'utilisation des MSQ :

/* Lecture message et destruction msq */ #include <sys/types.h> #include <sys/ipc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define CLE 17 struct msgbuf { long le_type; /* type du message */ char mtext[20]; /* texte du message */ }; main() { int msqid; struct msgbuf msgp; int x; while (1) { msqid = msgget((key_t)CLE, 0); /* rcup msqid*/ x=msgrcv(msqid,&msgp,19,(long)12,IPC_NOWAIT); if (x>-1) { msgp.mtext[x]=0; printf("message lu %d : %s\n",x,msgp.mtext); msgctl(msqid, IPC_RMID, NULL); exit(0); } } }

Les IPCs

La mmoire partage (SHM)

Zone mmoire commune plusieurs processus Identificateur SHM : entier fourni par le systme la cration

shmid

Attachement de cette zone par les processus utilisateurs Donnes non types Aucune filiation exige Lecture non destructrice: zone mmoire Structure associe : fichier shm.h

Les IPCs

La mmoire partage (SHM)

Les IPCs

La mmoire partage (SHM)

Cration SHM avec une cl


Rcupration de lidentificateur shmid Autorisation daccs par le crateur Fournir shmid Rcupration pointeur dbut zone SHM Accs mmoire

Attachement SHM par un processus


Lecture ou criture

Dtachement SHM par chaque processus Libration SHM par le processus crateur

Les IPCs

La mmoire partage (SHM)

Accs aux files via shmget()


Cration d'une nouvelle zone de mmoire partage Accs une zone dj existante

Prototype : int shmget(key_t cle, int taille, int option) Retourne l'identifiant shmid de la zone, sinon -1 et errno est :

EACCESS : Problme de droits EEXIST : Une IPC existe dj ce numro EIDRM : IPC dtruite EINVAL : Paramtres invalides ENOMEM : Table des IPCs sature ENOENT : Pas de mmoire partage la cl spcifie EFAULT : Paramtres incorrects ENOSPC : Toutes les identifications de mmoires partages sont utilises

Les IPCs

La mmoire partage (SHM)

Cration :

int shmget(cle,taille,IPC_CREAT | IPC_EXCL | 0660); Retourne le shmid, sinon -1. IPC_EXCL permet l'exclusivit (erreur si cl existe dj) Sans cl :

Utilisation de IPC_PRIVATE comme cl Rcupration d'un shmid :

shmget(cle, 0); int shmctl(int shmid, int op, struct shmid_ds *buf)

Contrle :

Destruction d'une SHM : shmctl(cle, IPC_RMID, NULL); IPC_STAT lecture de la structure dans buf IPC_SET modification de la structure partir de buf

Les IPCs

La mmoire partage (SHM)

Attachement :

void *shmat(int shmid,const void *shmadd,int option);


*shmadd = 0 : la rgion est attache la premire adresse disponible *shmadd != 0 et :

La SHM est attache au segment de donnes du processus l'adresse spcifie par *shmadd :

option contient SHM_RND : attache l'adresse (shmadd modulo SHMLBA) option ne contient pas SHM_RND : attache l'adresse shmadd

Lecture seule possible avec l'option SHM_RDONLY Retourne l'adresse de la rgion partage en cas de succs, sinon -1 et errno est :

EACESS : Problme de droits EINVAL : Cl ou adresse invalide EIDRM : Ressource dtruite ENOMEM : La mmoire est insuffisante

Un processus fils hrite de toutes les zones mmoires partages attaches l'espace d'adressage de son pre

Les IPCs

La mmoire partage (SHM)

Dtachement :

void *shmdt(const void *shmadd);

La rgion de mmoire dtache devient inaccessible pour le processus appelant. La terminaison d'un processus entrane le dtachement de toutes les rgions qu'il avait pralablement attaches son espace d'adressage.

Exemple d'utilisation des SHM :

Les IPCs

/* Programme crivain */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #define CLE 217 main(){ int shmid; /* id de la shm*/ char *mem; /* pointeur shm*/ /* cration shm avec la cl CLE */ if ((shmid=shmget((key_t)CLE,1000,IPC_CREAT|0750))==-1){ perror("shmget"); exit(1); } /* attachement */ if ((mem=shmat(shmid,NULL,0))==(char *)-1){ perror("shmat"); exit(2); } /* criture sans shm*/ strcpy(mem, "je suis le programme p1"); exit(0); }

Exemple d'utilisation des SHM :

Les IPCs

/* Programme lecteur et destructeur */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #define CLE 217 main () { int shmid; /* id de la shm */ char *mem; /* pointeur shm */ if ((shmid=shmget((key_t) CLE,0,0))<0) { /*rcupration shmid*/ perror("shmget"); exit(1); } if ((mem=shmat(shmid,NULL,0))==(char *)-1){ /*attachement la shm*/ perror("shmat"); exit(2); } printf("lu: %s\n", mem); /* lecture de la shm */ if (shmdt(mem)){ /* dtachement du processus */ perror("shmdt"); exit(3); } shmctl(shmid, IPC_RMID, NULL); /* destruction shm */ exit(0); }