begin process at 2012 05 27 14:43:36
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Système

 > COMMUNICATION INTER PROCESSUS PAR IPC SOUS *NIX

COMMUNICATION INTER PROCESSUS PAR IPC SOUS *NIX


 Information sur la source

Note :
Aucune note
Catégorie :Système Classé sous :linux, communication, processus, ipc, timer Niveau :Initié Date de création :30/05/2006 Date de mise à jour :02/06/2006 07:50:08 Vu / téléchargé :9 875 / 315

Auteur : AlexN

Ecrire un message privé
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (5)
Ajouter un commentaire et/ou une note


 Description

Ce programme illustre l'utilisation des mécanismes de communication inter processus par IPC avec les systèmes d'exploitation reprenant l'implémentation IPC SYSTEM V. Si vous voulez plus d'information sur ce sujet, je vous invite à lire le tutorial qui va avec et qui est posté sur le même site CS.
Ce programme illustre également la mise en place d'un mécanisme de temporisation par l'intermédiaire des signaux et/ou du timer système.
Le scénario global est l'envoi de signaux SIGUSR1 par l'emetteur au récepteur. Puis toutes les 2 secondes, les deux processus affichent l'un combien il en a envoyé et l'autre combien il en a reçu.

Note : la synchronisation n'est pas réalisée sur l'émission/réception des signaux, pour montrer la faiblesse de ces mécanismes (ils sont plus anciens que les IPC). Comme vous le montrera une exécution, l'émetteur envoie plus de signaux que n'en reçoit le récepteur. L'émetteur envoie ses signaux en rafale, et comme il n'existe qu'un seul "slot" système pour chaque signal, certains sont écrasés avant que le récepteur n'ait le temps de les capter.

Source

  • //
  • // Fichier d'entête commune : msg.h
  • //
  • /* type booleen */
  • enum { FAUX, VRAI };
  • /* Mode d'alarme utilisable (alarme simple ou timer) */
  • enum { NOALRM, ALARM, TIMER };
  • /* mode d'ipc utilisable (file de messages ou segment de memoire partage */
  • enum { NOIPC, MSG, SHM };
  • /* type des messages attendus */
  • enum { MSGPIDE = 1, MSGPIDR, MSGALRM, MSGIPC, MSGCPT };
  • /* structure des messages ipc */
  • typedef struct bufipc {
  • long mtype; /* type de message */
  • int info; /* contenu du message */
  • } msgipc;
  • /* structure d'un message par segment de memoire partage */
  • typedef struct bufshm {
  • int pide; /* pid de l'emetteur */
  • int pidr; /* pid du recepteur */
  • int ModeAlrm; /* mode d'alarme */
  • int cptr; /* nombre de signaux recus */
  • } msgshm;
  • /* 256 octets pour un segment de memoire partage */
  • #define TAILLESHM 256
  • //
  • // Fichier emetteur.c
  • //
  • /*
  • Petit exercice sur les IPC
  • Auteur : Le gaijin
  • Fichier : emetteur.c = emetteur de signaux
  • Scenario :
  • 1) Un fork,
  • Parent a un compteur de SIGUSR1 recus
  • Enfant a un compteur de SIGUSR1 emis
  • 2) Enfant envoit l'alarme toute les 2 secondes a Parent
  • 3) une fonction unique pour la gestion de tous les signaux
  • 4) un gestionnaire global des signaux
  • 5) Couper le fichier en deux :
  • - un avec le code du pere
  • - un avec le code du fils
  • apres le fork, on fait un exec pour lancer le fils
  • on passe le pid du pere dans les arguments
  • 6) Plus de fork : un emetteur, un recepteur, les IPC
  • - emetteur : l'ancien fils
  • - recepteur : l'ancien pere
  • Communication par IPC-file de messages :
  • Avant de demarrer la sequence des signaux, les processus se synchronisent :
  • - le premier processus lance determine la methode de travail (ALARM ou TIMER)
  • et la communique au second.
  • - Communication respective de leur PID pour la synchronisation des terminaisons
  • - A chaque alarme, Recepteur envoie son compteur de signaux recus par la file
  • de messages
  • Synchronisation par signal :
  • le processus qui recoit le signal de terminaison le regenere pour l'autre
  • afin de synchroniser leur terminaison
  • 7) Double canal de communication : file de message et segment de memoire partage :
  • - D'abord par la file de message pour savoir quelle sera la methode de
  • communication dans la suite du programme (file ou segment)
  • N.B. : Les deux IPC utilisent la meme cle
  • Communication par IPC-segment de memoire partages :
  • - A chaque alarme, Recepteur ecrit la valeur de son compteur de signaux recus
  • dans le segment
  • 8) Correction des bugs
  • Raffinement de la sortie du programme (atexit), pour nettoyer les IPC.
  • */
  • #include <sys/time.h>
  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>
  • #include <sys/shm.h>
  • #include <stdlib.h>
  • #include <stdio.h>
  • #include <errno.h>
  • #include <signal.h>
  • #include <getopt.h>
  • #include "msg.h"
  • /* Macro pour la lisibilite */
  • #define ERREUR(msg) { perror(msg); exit(errno); }
  • /* Qui est le premier processus lance (emetteur ou recepteur) */
  • int EmetteurPremier = FAUX;
  • /* Mode d'alarme (alarme simple ou timer) */
  • int ModeAlarme = NOALRM;
  • /* Mode d'IPC (file de messages ou segment de memoire partage) */
  • int ModeIPC = NOIPC;
  • int cpte = 0; /* compteur de signaux emis */
  • int cptr = 0; /* compteur de signaux recus */
  • int pidr = 0; /* pid du recepteur */
  • key_t cle = 0; /* cle de l'ipc */
  • int msqid = 0; /* dipc de la file de messages */
  • int shmid = 0; /* dipc du segment de memoire */
  • msgshm *seg = NULL; /* adresse du debut du segment */
  • msgipc message; /* un message IPC */
  • struct msqid_ds md; /* pour les stats de la file de messages */
  • struct shmid_ds sd; /* pour les stats du segment de memoire */
  • /* Affichage des usages */
  • void AfficherLesUsages (char **argv) {
  • printf("Usage : %s [-t(imer)|-a(larm)] [-m(essages)|-s(egment)]\n", argv[0]);
  • exit (1);
  • }
  • /* fonction de terminaison du programme */
  • void DetruireIPC (void) {
  • msgctl(msqid, IPC_RMID, NULL); /* detruire la file de messages */
  • if (ModeIPC == SHM )
  • shmctl(shmid, IPC_RMID, NULL); /* detruire le segment de memoire */
  • }
  • /* gestionnaire global des signaux */
  • void GestSig (int sig, siginfo_t *siginfo, void *pvoid) {
  • switch (sig) {
  • case SIGALRM:
  • kill(pidr, SIGALRM); /* envoi du signal de synchro au recepteur */
  • switch (ModeIPC) {
  • case MSG:
  • /* reception du message du recepteur : nombre de signaux recus */
  • if (msgrcv (msqid, &message, sizeof(message.info), MSGCPT, 0) == -1 )
  • ERREUR("msgrcv emetteur")
  • /* mise a jour de cptr en fonction du message recu */
  • cptr = message.info;
  • break;
  • case SHM:
  • /* lire le nombre de signaux recus dans le segment */
  • while (cptr == seg->cptr); /* synchro optionnelle */
  • cptr = seg->cptr; /* lecture du compteur depuis le segment */
  • break;
  • }
  • /* rearmement de l'alarme */
  • if (ModeAlarme == ALARM) alarm(2);
  • /* affichage du message apres synchro */
  • printf("Emetteur = %8d, Recepteur = %8d\n", cpte, cptr);
  • break;
  • case SIGINT:
  • kill (pidr, SIGINT); /* regenerer le signal pour le recepteur */
  • exit(errno);
  • break;
  • }
  • }
  • int main (int argc, char **argv) {
  • struct sigaction act;
  • struct itimerval val, oval;
  • int c;
  • /* gestion de la terminaison */
  • atexit (DetruireIPC);
  • /* gestion des arguments */
  • if (argc != 1) {
  • while ( (c = getopt(argc, argv, "atms")) != EOF ) {
  • switch ( c ) {
  • case 'a' : ModeAlarme = ALARM; break;
  • case 't' : ModeAlarme = TIMER; break;
  • case 'm' : ModeIPC = MSG; break;
  • case 's' : ModeIPC = SHM; break;
  • default : AfficherLesUsages(argv); break;
  • }
  • }
  • }
  • /* Armement des signaux */
  • act.sa_flags = SA_SIGINFO;
  • act.sa_sigaction = GestSig;
  • sigemptyset (&act.sa_mask);
  • if ( sigaction (SIGUSR1, &act, NULL) == -1 ) ERREUR("sigaction SIGUSR1")
  • if ( sigaction (SIGALRM, &act, NULL) == -1 ) ERREUR("sigaction SIGALRM")
  • if ( sigaction (SIGINT, &act, NULL) == -1 ) ERREUR("sigaction SIGINT")
  • /* creer ou retrouver l'ipc */
  • if ( (cle = ftok ("/bin", 'a')) == -1 ) ERREUR("ftok emetteur")
  • /* lire d'abord la file de message pour savoir si emetteur est le premier */
  • /* processus lance, auquel cas */
  • /* il impose le mode d'ipc et le mode d'alarme (alarme ou timer) */
  • if ( (msqid = msgget (cle, IPC_CREAT|0660)) == -1 )
  • ERREUR("msgget emetteur")
  • /* obtenir les stats de la file de message pour savoir qui est le createur */
  • /* et donc qui impose le mode d'ipc et le mode d'alarme (alarme ou timer) */
  • if ( msgctl (msqid, IPC_STAT, &md) == -1 )
  • ERREUR("msgctl emetteur IPC_STAT")
  • /* Est-ce qu'un message a deja ete envoye par un autre processus ? */
  • if ( md.msg_lspid == 0 ) {
  • EmetteurPremier = VRAI;
  • /* Emetteur est le createur : il impose le mode d'ipc */
  • if ( ModeIPC == NOIPC ) ModeIPC = MSG; /* forcer le mode d'IPC */
  • /* preparer le message */
  • message.mtype = MSGIPC;
  • message.info = ModeIPC;
  • /* envoyer le message : mode d'IPC */
  • if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
  • ERREUR("msgsnd emetteur MSGIPC")
  • } else {
  • /* Emetteur n'est pas le createur */
  • /* lire un autre message : mode d'ipc */
  • if ( msgrcv (msqid, &message, sizeof(message.info), MSGIPC, 0) == -1 )
  • ERREUR("msgrcv emetteur MSGIPC")
  • if ( ModeIPC == NOIPC )
  • ModeIPC = message.info;
  • else
  • if ( ModeIPC != message.info ) {
  • printf ("Emetteur n'est pas le createur, mode d'ipc deja donne : %s\n",
  • (ModeIPC = message.info) == MSG ? "Message" : "Segment");
  • }
  • }
  • switch (ModeIPC) {
  • case MSG:
  • if ( EmetteurPremier ) {
  • /* Emetteur est le createur : il impose le mode d'alarme */
  • /* et la communique au recepteur */
  • /* envoyer un message : mode d'alarme utilise */
  • if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
  • /* preparer le message */
  • message.mtype = MSGALRM;
  • message.info = ModeAlarme;
  • /* envoyer le message : mode d'alarme */
  • if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
  • ERREUR("msgsnd emetteur MSGALRM")
  • } else {
  • /* Emetteur n'est pas le createur */
  • /* lire un autre message : mode d'alarme */
  • if ( msgrcv (msqid, &message, sizeof(message.info), MSGALRM, 0) == -1 )
  • ERREUR("msgrcv emetteur MSGALRM")
  • if ( ModeAlarme == NOALRM )
  • ModeAlarme = message.info;
  • else
  • if ( ModeAlarme != message.info )
  • printf ("Emetteur n'est pas le createur, mode d'alarme deja donne : %s\n",
  • (ModeAlarme = message.info) == ALARM ? "ALARM" : "TIMER");
  • }
  • /* preparer le message */
  • message.mtype = MSGPIDE;
  • message.info = getpid();
  • /* envoyer le message : pid de l'emetteur */
  • if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
  • ERREUR("msgsnd emetteur MSGPIDE")
  • /* attente bloquante du premier message, le pid du recepteur */
  • if ( msgrcv (msqid, &message, sizeof(message.info), MSGPIDR, 0) == -1 )
  • ERREUR("msgrcv emetteur")
  • /* initialiser le pidr en fonction du message recu */
  • pidr = message.info;
  • break;
  • case SHM:
  • /* creer ou retrouver le segment de memoire partage et le mapper */
  • if ( (shmid = shmget (cle, TAILLESHM, IPC_CREAT|0660)) == -1 )
  • ERREUR("shmget emetteur")
  • if ( (seg = (msgshm *) shmat(shmid, NULL, 0)) == NULL )
  • ERREUR("shmat emetteur")
  • if ( EmetteurPremier ) {
  • /* Emetteur est le createur : il impose le mode d'alarme */
  • /* et la communique au recepteur */
  • if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
  • seg->pide = getpid(); /* ecrire le pid de l'emetteur */
  • seg->ModeAlrm = ModeAlarme; /* imposer le mode d'alarme */
  • while ( !(pidr = seg->pidr) ); /* attendre le pid du recepteur */
  • } else {
  • seg->pide = getpid(); /* ecrire le pid de l'emetteur */
  • while ( !(pidr = seg->pidr) ); /* attendre le pid du recepteur */
  • if ( ModeAlarme == NOALRM )
  • ModeAlarme = seg->ModeAlrm; /* lire le mode d'alarme du recepteur */
  • else
  • if ( ModeAlarme != seg->ModeAlrm )
  • printf ("Emetteur n'est pas le createur, mode d'alarme deja donne : %s\n",
  • (ModeAlarme = seg->ModeAlrm) == ALARM ? "ALARM" : "TIMER");
  • }
  • break;
  • }
  • /* mise en place du mode d'alarme */
  • switch (ModeAlarme) {
  • case ALARM :
  • alarm(2);
  • break;
  • case TIMER :
  • /* mise en place du timer */
  • val.it_interval.tv_sec = 2; /* toutes les deux secondes */
  • val.it_interval.tv_usec = 0;
  • val.it_value.tv_sec = 2; /* a partir de la 2 eme seconde du prog */
  • val.it_value.tv_usec = 0;
  • setitimer (ITIMER_REAL, &val, &oval); /* Armement du timer */
  • break;
  • }
  • /* message d'initialisation */
  • printf ("Emetteur (pid = %-8d) : %s IPC et Mode %s\n", getpid(),
  • ModeIPC == MSG ? "Message" : "Segment",
  • ModeAlarme == ALARM ? "ALARM" : "TIMER");
  • /* emission des signaux */
  • while (1) {
  • kill(pidr,SIGUSR1);
  • cpte++;
  • }
  • }
  • #undef ERREUR
  • //
  • // Fichier recepteur.c
  • //
  • #include <sys/time.h>
  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>
  • #include <sys/shm.h>
  • #include <stdlib.h>
  • #include <stdio.h>
  • #include <errno.h>
  • #include <signal.h>
  • #include <getopt.h>
  • #include "msg.h"
  • /* Macro pour la lisibilite */
  • #define ERREUR(msg) { perror(msg); exit(errno); }
  • /* Qui est le premier processus lance (emetteur ou recepteur) */
  • int RecepteurPremier = FAUX;
  • /* Mode d'alarme (alarme simple ou timer) */
  • int ModeAlarme = NOALRM;
  • /* Mode d'IPC (file de messages ou segment de memoire partage) */
  • int ModeIPC = NOIPC;
  • int pide = 0; /* pid de l'emetteur */
  • key_t cle = 0; /* cle de l'ipc */
  • int msqid = 0; /* dipc de la file de messages */
  • int shmid = 0; /* dipc du segment de memoire */
  • msgshm *seg = NULL; /* adresse de debut du segment */
  • msgipc message; /* un message IPC */
  • struct msqid_ds md; /* pour les stats de la file de messages */
  • struct shmid_ds sd; /* pour les stats du segment de memoire */
  • /* Affichage des usages */
  • void AfficherLesUsages (char **argv) {
  • printf("Usage : %s [-t(imer)|-a(larm)] [-m(essages)|-s(egment)]\n", argv[0]);
  • exit (1);
  • }
  • /* fonction de terminaison du programme */
  • void DetruireIPC (void) {
  • msgctl(msqid, IPC_RMID, NULL); /* detruire la file de messages */
  • if (ModeIPC == SHM )
  • shmctl(shmid, IPC_RMID, NULL); /* detruire le segment de memoire */
  • }
  • /* gestionnaire global des signaux */
  • void GestSig (int sig, siginfo_t *siginfo, void *pvoid) {
  • static int cptr = 0; /* compteurs de signaux recus */
  • switch (sig) {
  • case SIGUSR1 :
  • cptr++;
  • break;
  • case SIGALRM:
  • switch (ModeIPC) {
  • case MSG:
  • /* preparer le message */
  • message.mtype = MSGCPT;
  • message.info = cptr;
  • /* envoyer le message : nombre de signaux recus */
  • if (msgsnd (msqid, &message, sizeof (message.info), 0) == -1)
  • ERREUR("msgsnd recepteur MSGCPT")
  • break;
  • case SHM:
  • /* ecriture du nombre de signaux recus dans le segment */
  • seg->cptr = cptr;
  • break;
  • }
  • break;
  • case SIGINT:
  • kill (pide, SIGINT); /* regenerer le signal pour l'emetteur */
  • exit(errno);
  • break;
  • }
  • }
  • int main (int argc, char **argv) {
  • struct sigaction act;
  • struct itimerval val, oval;
  • int c;
  • /* gestion de la terminaison */
  • atexit (DetruireIPC);
  • /* gestion des arguments */
  • if (argc != 1)
  • while ( (c = getopt(argc, argv, "atms")) != EOF ) {
  • switch ( c ) {
  • case 'a' : ModeAlarme = ALARM; break;
  • case 't' : ModeAlarme = TIMER; break;
  • case 'm' : ModeIPC = MSG; break;
  • case 's' : ModeIPC = SHM; break;
  • default : AfficherLesUsages(argv); break;
  • }
  • }
  • /* Armement des signaux */
  • act.sa_flags = SA_SIGINFO;
  • act.sa_sigaction = GestSig;
  • sigemptyset (&act.sa_mask);
  • if ( sigaction (SIGUSR1, &act, NULL) == -1 ) ERREUR("sigaction SIGUSR1")
  • if ( sigaction (SIGALRM, &act, NULL) == -1 ) ERREUR("sigaction SIGALRM")
  • if ( sigaction (SIGINT, &act, NULL) == -1 ) ERREUR("sigaction SIGINT")
  • /* creer ou retrouver l'ipc */
  • if ( (cle = ftok ("/bin", 'a')) == -1 ) ERREUR("ftok recepteur")
  • /* lire d'abord la file de message pour savoir si recepteur est le premier */
  • /* processus lance, auquel cas */
  • /* il impose le mode d'ipc et le mode d'alarme (alarme ou timer) */
  • if ( (msqid = msgget (cle, IPC_CREAT|0660)) == -1 )
  • ERREUR("msgget recepteur")
  • /* obtenir les stats de la file de message pour savoir qui est le createur */
  • /* et donc qui impose le mode d'ipc et le mode d'alarme (alarme ou timer) */
  • if ( msgctl (msqid, IPC_STAT, &md) == -1 )
  • ERREUR("msgctl recepteur IPC_STAT")
  • /* Est-ce qu'un message a deja ete envoye par un autre processus ? */
  • if ( md.msg_lspid == 0 ) {
  • RecepteurPremier = VRAI;
  • /* Recepteur est le createur : il impose le mode d'ipc */
  • if ( ModeIPC == NOIPC ) ModeIPC = MSG; /* forcer le mode d'IPC */
  • /* preparer le message */
  • message.mtype = MSGIPC;
  • message.info = ModeIPC;
  • /* envoyer le message : mode d'IPC */
  • if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
  • ERREUR("msgsnd recepteur MSGIPC")
  • } else {
  • /* Recepteur n'est pas le createur */
  • /* lire un autre message : mode d'ipc */
  • if ( msgrcv (msqid, &message, sizeof(message.info), MSGIPC, 0) == -1 )
  • ERREUR("msgrcv recepteur MSGIPC")
  • if ( ModeIPC == NOIPC )
  • ModeIPC = message.info;
  • else
  • if ( ModeIPC != message.info ) {
  • printf ("Recepteur n'est pas le createur, mode d'ipc deja donne : %s\n",
  • (ModeIPC = message.info) == MSG ? "Message" : "Segment");
  • }
  • }
  • switch (ModeIPC) {
  • case MSG:
  • if ( (msqid = msgget (cle, IPC_CREAT|0660)) == -1 )
  • ERREUR("msgget recepteur")
  • /* obtenir les stats de la liste d'ipc pour savoir qui est le createur */
  • /* et donc qui impose le mode d'alarme (alarm ou timer) */
  • if ( msgctl (msqid, IPC_STAT, &md) == -1 )
  • ERREUR("msgctl emetteur IPC_STAT")
  • if ( RecepteurPremier ) {
  • /* Recepteur est le createur : il impose le mode d'alarme */
  • /* et la communique au recepteur */
  • /* envoyer un message : mode d'alarme utilise */
  • if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
  • /* preparer le message */
  • message.mtype = MSGALRM;
  • message.info = ModeAlarme;
  • /* envoyer le message : mode d'alarme */
  • if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
  • ERREUR("msgsnd recepteur MSGALRM")
  • } else {
  • /* Recepteur n'est pas le createur */
  • /* lire un message : mode d'alarme */
  • if ( msgrcv (msqid, &message, sizeof(message.info), MSGALRM, 0) == -1 )
  • ERREUR("msgrcv recepteur MSGALRM")
  • if ( ModeAlarme == NOALRM )
  • ModeAlarme = message.info;
  • else
  • if ( ModeAlarme != message.info )
  • printf ("Recepteur n'est pas le createur, mode d'alarme deja donne : %s\n",
  • (ModeAlarme = message.info) == ALARM ? "ALARM": "TIMER");
  • }
  • /* preparer le message */
  • message.mtype = MSGPIDR;
  • message.info = getpid();
  • /* envoyer le message : pid du recepteur */
  • if (msgsnd (msqid, &message, sizeof (message.info), 0) == -1)
  • ERREUR("msgsnd recepteur MSGPIDR")
  • /* attente bloquante du pid de l'emetteur */
  • if (msgrcv (msqid, &message, sizeof(message.info), MSGPIDE, 0) == -1)
  • ERREUR("msgrcv recepteur")
  • /* initialiser le pide en fonction du message recu */
  • pide = message.info;
  • break;
  • case SHM:
  • /* creer ou retrouver le segment de memoire partage et le mapper */
  • if ( (shmid = shmget (cle, TAILLESHM, IPC_CREAT|0660)) == -1 )
  • ERREUR("shmget recepteur")
  • if ( (seg = (msgshm *) shmat(shmid, NULL, 0)) == NULL )
  • ERREUR("shmat recepteur")
  • if ( RecepteurPremier ) {
  • /* Recepteur est le createur : il impose le mode d'alarme */
  • /* et la communique a l'emetteur */
  • if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
  • seg->pidr = getpid(); /* ecrire le pid de l'emetteur */
  • seg->ModeAlrm = ModeAlarme; /* imposer le mode d'alarme */
  • while ( !(pide = seg->pide) ); /* attendre que le pid de l'emetteur */
  • } else {
  • seg->pidr = getpid(); /* ecrire le pid du recepteur */
  • while ( !(pide = seg->pide) ); /* attendre que le pid de l'emetteur */
  • if ( ModeAlarme == NOALRM )
  • ModeAlarme = seg->ModeAlrm; /* lire le mode d'alarme du recepteur */
  • else
  • if ( ModeAlarme != seg->ModeAlrm )
  • printf ("Recepteur n'est pas le createur, mode d'alarme deja donne : %s\n",
  • (ModeAlarme = seg->ModeAlrm) == ALARM ? "ALARM" : "TIMER");
  • }
  • break;
  • }
  • /* message d'initialisation */
  • printf ("Recepteur (pid = %-8d) : %s IPC et Mode %s\n", getpid(),
  • ModeIPC == MSG ? "Message" : "Segment",
  • ModeAlarme == ALARM ? "ALARM" : "TIMER");
  • /* attente des signaux et de la terminaison de l'emetteur */
  • while (1) pause();
  • }
  • #undef ERREUR
//
// Fichier d'entête commune : msg.h
//
/* type booleen */
enum { FAUX, VRAI };

/* Mode d'alarme utilisable (alarme simple ou timer) */
enum { NOALRM, ALARM, TIMER };

/* mode d'ipc utilisable (file de messages ou segment de memoire partage */
enum { NOIPC, MSG, SHM };

/* type des messages attendus */
enum { MSGPIDE = 1, MSGPIDR, MSGALRM, MSGIPC, MSGCPT };

/* structure des messages ipc */
typedef struct bufipc {
	long mtype; /* type de message */
	int info;   /* contenu du message */
} msgipc;

/* structure d'un message par segment de memoire partage */
typedef struct bufshm {
	int pide;		/* pid de l'emetteur */
	int pidr;		/* pid du recepteur  */
	int ModeAlrm;	/* mode d'alarme */
	int cptr;		/* nombre de signaux recus */
} msgshm;

/* 256 octets pour un segment de memoire partage */
#define TAILLESHM 256


//
// Fichier emetteur.c
//
/* 
Petit exercice sur les IPC
Auteur   : Le gaijin
Fichier  : emetteur.c = emetteur de signaux
Scenario :
 
1) Un fork, 
Parent a un compteur de SIGUSR1 recus
Enfant a un compteur de SIGUSR1 emis
2) Enfant envoit l'alarme toute les 2 secondes a Parent
3) une fonction unique pour la gestion de tous les signaux
4) un gestionnaire global des signaux

5) Couper le fichier en deux :
- un avec le code du pere
- un avec le code du fils
apres le fork, on fait un exec pour lancer le fils
on passe le pid du pere dans les arguments

6) Plus de fork : un emetteur, un recepteur, les IPC
- emetteur  : l'ancien fils 
- recepteur : l'ancien pere

Communication par IPC-file de messages :
Avant de demarrer la sequence des signaux, les processus se synchronisent :
- le premier processus lance determine la methode de travail (ALARM ou TIMER)
  et la communique au second.
- Communication respective de leur PID pour la synchronisation des terminaisons
- A chaque alarme, Recepteur envoie son compteur de signaux recus par la file 
  de messages

Synchronisation par signal :
le processus qui recoit le signal de terminaison le regenere pour l'autre
afin de synchroniser leur terminaison

7) Double canal de communication : file de message et segment de memoire partage :
- D'abord par la file de message pour savoir quelle sera la methode de 
  communication dans la suite du programme (file ou segment)

N.B. : Les deux IPC utilisent la meme cle

Communication par IPC-segment de memoire partages :
- A chaque alarme, Recepteur ecrit la valeur de son compteur de signaux recus
  dans le segment

8) Correction des bugs
Raffinement de la sortie du programme (atexit), pour nettoyer les IPC.
*/

#include <sys/time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <getopt.h>

#include "msg.h"

/* Macro pour la lisibilite */
#define ERREUR(msg) { perror(msg); exit(errno); }

/* Qui est le premier processus lance (emetteur ou recepteur) */
int EmetteurPremier = FAUX;

/* Mode d'alarme (alarme simple ou timer) */
int ModeAlarme = NOALRM;

/* Mode d'IPC (file de messages ou segment de memoire partage) */
int ModeIPC = NOIPC;

int cpte  = 0;       /* compteur de signaux emis  */
int cptr  = 0;       /* compteur de signaux recus */

int pidr  = 0;       /* pid du recepteur */

key_t cle = 0;       /* cle de l'ipc */
int msqid = 0;       /* dipc de la file de messages */
int shmid = 0;       /* dipc du segment de memoire  */
msgshm *seg = NULL;  /* adresse du debut du segment */

msgipc message;      /* un message IPC */

struct msqid_ds md;  /* pour les stats de la file de messages */
struct shmid_ds sd;  /* pour les stats du segment de memoire  */

/* Affichage des usages */
void AfficherLesUsages (char **argv) {
	printf("Usage : %s [-t(imer)|-a(larm)] [-m(essages)|-s(egment)]\n", argv[0]);
	exit (1);
}		

/* fonction de terminaison du programme */
void DetruireIPC (void) {
	msgctl(msqid, IPC_RMID, NULL);		/* detruire la file de messages   */
	if (ModeIPC == SHM )
		shmctl(shmid, IPC_RMID, NULL);	/* detruire le segment de memoire */
}

/* gestionnaire global des signaux */
void GestSig (int sig, siginfo_t *siginfo, void *pvoid) {

	switch (sig) {
	case SIGALRM:
		kill(pidr, SIGALRM); /* envoi du signal de synchro au recepteur */
		switch (ModeIPC) {
		case MSG:
			/* reception du message du recepteur : nombre de signaux recus */
			if (msgrcv (msqid, &message, sizeof(message.info), MSGCPT, 0) == -1 )
				ERREUR("msgrcv emetteur")
			/* mise a jour de cptr en fonction du message recu */
			cptr = message.info;
			break;
		case SHM:
			/* lire le nombre de signaux recus dans le segment */
			while (cptr == seg->cptr); /* synchro optionnelle  */
			cptr = seg->cptr; /* lecture du compteur depuis le segment */
			break;
		}
	
		/* rearmement de l'alarme */	
		if (ModeAlarme == ALARM) alarm(2);
		
		/* affichage du message apres synchro */
		printf("Emetteur = %8d, Recepteur = %8d\n", cpte, cptr);
		break;
	case SIGINT:
		kill (pidr, SIGINT); /* regenerer le signal pour le recepteur */
		exit(errno);
		break;
	}
}

int main (int argc, char **argv) {
struct sigaction act;
struct itimerval val, oval;
int c;

	/* gestion de la terminaison */
	atexit (DetruireIPC);

	/* gestion des arguments */
	if (argc != 1) {
		while ( (c = getopt(argc, argv, "atms")) != EOF ) {
			switch ( c ) {
				case 'a' : ModeAlarme = ALARM;      break;
				case 't' : ModeAlarme = TIMER;      break;
				case 'm' : ModeIPC    = MSG;        break;
				case 's' : ModeIPC    = SHM;        break;
				default  : AfficherLesUsages(argv); break;
			}
		}
	}
	
	/* Armement des signaux */
	act.sa_flags = SA_SIGINFO;
	act.sa_sigaction = GestSig;
	sigemptyset (&act.sa_mask);
	if ( sigaction (SIGUSR1, &act, NULL) == -1 ) ERREUR("sigaction SIGUSR1")
	if ( sigaction (SIGALRM, &act, NULL) == -1 ) ERREUR("sigaction SIGALRM")
	if ( sigaction (SIGINT,  &act, NULL) == -1 ) ERREUR("sigaction SIGINT")
	
	/* creer ou retrouver l'ipc */
	if ( (cle = ftok ("/bin", 'a')) == -1 )      ERREUR("ftok emetteur")

	/* lire d'abord la file de message pour savoir si emetteur est le premier */
	/* processus lance, auquel cas                                            */
	/* il impose le mode d'ipc et le mode d'alarme (alarme ou timer)          */
	if ( (msqid = msgget (cle, IPC_CREAT|0660)) == -1 )
		ERREUR("msgget emetteur")
	
	/* obtenir les stats de la file de message pour savoir qui est le createur */
	/* et donc qui impose le mode d'ipc et le mode d'alarme (alarme ou timer)  */
	if ( msgctl (msqid, IPC_STAT, &md) == -1 )
		ERREUR("msgctl emetteur IPC_STAT")

	/* Est-ce qu'un message a deja ete envoye par un autre processus ? */
	if ( md.msg_lspid == 0 ) {
		EmetteurPremier = VRAI;
		/* Emetteur est le createur : il impose le mode d'ipc */
		if ( ModeIPC == NOIPC ) ModeIPC = MSG; /* forcer le mode d'IPC */
		/* preparer le message */
		message.mtype = MSGIPC;
		message.info  = ModeIPC;
		/* envoyer le message : mode d'IPC */
		if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
			ERREUR("msgsnd emetteur MSGIPC")
	} else {
		/* Emetteur n'est pas le createur        */
		/* lire un autre message : mode d'ipc    */
		if ( msgrcv (msqid, &message, sizeof(message.info), MSGIPC, 0) == -1 )
			ERREUR("msgrcv emetteur MSGIPC")
		if ( ModeIPC == NOIPC )
			ModeIPC = message.info;
		else
			if ( ModeIPC != message.info ) {
				printf ("Emetteur n'est pas le createur, mode d'ipc deja donne    : %s\n", 
					(ModeIPC = message.info) == MSG ? "Message" : "Segment");
		}
	}

	switch (ModeIPC) {
	case MSG:
		if ( EmetteurPremier ) {
		/* Emetteur est le createur : il impose le mode d'alarme */
		/* et la communique au recepteur                         */
			/* envoyer un message : mode d'alarme utilise         */
			if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
			/* preparer le message */
			message.mtype = MSGALRM;
			message.info  = ModeAlarme;
			/* envoyer le message : mode d'alarme */
			if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
				ERREUR("msgsnd emetteur MSGALRM")
		} else {
		/* Emetteur n'est pas le createur        */
		/* lire un autre message : mode d'alarme */
			if ( msgrcv (msqid, &message, sizeof(message.info), MSGALRM, 0) == -1 )
				ERREUR("msgrcv emetteur MSGALRM")
			if ( ModeAlarme == NOALRM )
				ModeAlarme = message.info;
			else
				if ( ModeAlarme != message.info ) 
					printf ("Emetteur n'est pas le createur, mode d'alarme deja donne : %s\n", 
						(ModeAlarme = message.info) == ALARM ? "ALARM" : "TIMER");
		}	

		/* preparer le message */
		message.mtype = MSGPIDE;
		message.info  = getpid();
		/* envoyer le message : pid de l'emetteur */
		if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
			ERREUR("msgsnd emetteur MSGPIDE")
	
		/* attente bloquante du premier message, le pid du recepteur */
		if ( msgrcv (msqid, &message, sizeof(message.info), MSGPIDR, 0) == -1 )
			ERREUR("msgrcv emetteur")

		/* initialiser le pidr en fonction du message recu */
		pidr = message.info;
		break;

	case SHM:
		/* creer ou retrouver le segment de memoire partage et le mapper */
		if ( (shmid = shmget (cle, TAILLESHM, IPC_CREAT|0660)) == -1 )
			ERREUR("shmget emetteur")
		if ( (seg = (msgshm *) shmat(shmid, NULL, 0)) == NULL )
			ERREUR("shmat emetteur")
		if ( EmetteurPremier ) {
			/* Emetteur est le createur : il impose le mode d'alarme                   */
			/* et la communique au recepteur                                           */
			if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
			seg->pide = getpid();			/* ecrire le pid de l'emetteur              */
			seg->ModeAlrm = ModeAlarme;		/* imposer le mode d'alarme                 */
			while ( !(pidr = seg->pidr) );	/* attendre le pid du recepteur             */
		} else {
			seg->pide = getpid();			/* ecrire le pid de l'emetteur              */
			while ( !(pidr = seg->pidr) );	/* attendre le pid du recepteur             */
			if ( ModeAlarme == NOALRM )
				ModeAlarme = seg->ModeAlrm; /* lire le mode d'alarme du recepteur       */
			else
				if ( ModeAlarme != seg->ModeAlrm )
					printf ("Emetteur n'est pas le createur, mode d'alarme deja donne : %s\n", 
						(ModeAlarme = seg->ModeAlrm) == ALARM ? "ALARM" : "TIMER");
		}
		break;
	}

	/* mise en place du mode d'alarme */
	switch (ModeAlarme) {
	case ALARM :
		alarm(2);
		break;
	case TIMER :
		/* mise en place du timer */
		val.it_interval.tv_sec  = 2; 	/* toutes les deux secondes */
		val.it_interval.tv_usec = 0;
		val.it_value.tv_sec     = 2;	/* a partir de la 2 eme seconde du prog */ 
		val.it_value.tv_usec    = 0;
		setitimer (ITIMER_REAL, &val, &oval); /* Armement du timer */
		break;
	}

	/* message d'initialisation */
	printf ("Emetteur  (pid = %-8d) : %s IPC et Mode %s\n", getpid(), 
		ModeIPC    == MSG ?   "Message" : "Segment",
		ModeAlarme == ALARM ? "ALARM"   : "TIMER");

	/* emission des signaux */
	while (1) {
		kill(pidr,SIGUSR1);
		cpte++;
	}
}

#undef ERREUR


//
// Fichier recepteur.c
//
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <getopt.h>

#include "msg.h"

/* Macro pour la lisibilite */
#define ERREUR(msg) { perror(msg); exit(errno); }

/* Qui est le premier processus lance (emetteur ou recepteur) */
int RecepteurPremier = FAUX;

/* Mode d'alarme (alarme simple ou timer) */
int ModeAlarme = NOALRM;

/* Mode d'IPC (file de messages ou segment de memoire partage) */
int ModeIPC = NOIPC;

int pide  = 0;       /* pid de l'emetteur */

key_t cle = 0;       /* cle de l'ipc */
int msqid = 0;       /* dipc de la file de messages */
int shmid = 0;       /* dipc du segment de memoire  */
msgshm *seg = NULL;  /* adresse de debut du segment */

msgipc message;      /* un message IPC */

struct msqid_ds md;  /* pour les stats de la file de messages */
struct shmid_ds sd;  /* pour les stats du segment de memoire  */

/* Affichage des usages */
void AfficherLesUsages (char **argv) {
	printf("Usage : %s [-t(imer)|-a(larm)] [-m(essages)|-s(egment)]\n", argv[0]);
	exit (1);
}		

/* fonction de terminaison du programme */
void DetruireIPC (void) {
	msgctl(msqid, IPC_RMID, NULL);		/* detruire la file de messages   */
	if (ModeIPC == SHM )
		shmctl(shmid, IPC_RMID, NULL);	/* detruire le segment de memoire */
}

/* gestionnaire global des signaux */
void GestSig (int sig, siginfo_t *siginfo, void *pvoid) {
static int cptr = 0; /* compteurs de signaux recus */

	switch (sig) {
	case SIGUSR1 : 
		cptr++;
		break;
	case SIGALRM:
		switch (ModeIPC) {
		case MSG:
			/* preparer le message */
			message.mtype = MSGCPT;
			message.info  = cptr;
			/* envoyer le message : nombre de signaux recus */
			if (msgsnd (msqid, &message, sizeof (message.info), 0) == -1)
				ERREUR("msgsnd recepteur MSGCPT")
			break;
		case SHM:
			/* ecriture du nombre de signaux recus dans le segment */
			seg->cptr = cptr;
			break;
		}
		break;
	case SIGINT:
		kill (pide, SIGINT); /* regenerer le signal pour l'emetteur */
		exit(errno);
		break;
	}
}

int main (int argc, char **argv) {
struct sigaction act;
struct itimerval val, oval;
int c;

	/* gestion de la terminaison */
	atexit (DetruireIPC);

	/* gestion des arguments */
	if (argc != 1) 
		while ( (c = getopt(argc, argv, "atms")) != EOF ) {
			switch ( c ) {
				case 'a' : ModeAlarme = ALARM;      break;
				case 't' : ModeAlarme = TIMER;      break;
				case 'm' : ModeIPC    = MSG;        break;
				case 's' : ModeIPC    = SHM;        break;
				default  : AfficherLesUsages(argv); break;
			}
		}

	/* Armement des signaux */
	act.sa_flags = SA_SIGINFO;
	act.sa_sigaction = GestSig;
	sigemptyset (&act.sa_mask);
	if ( sigaction (SIGUSR1, &act, NULL) == -1 ) ERREUR("sigaction SIGUSR1")
	if ( sigaction (SIGALRM, &act, NULL) == -1 ) ERREUR("sigaction SIGALRM")
	if ( sigaction (SIGINT,  &act, NULL) == -1 ) ERREUR("sigaction SIGINT")

	/* creer ou retrouver l'ipc */ 
	if ( (cle = ftok ("/bin", 'a')) == -1 )      ERREUR("ftok recepteur")

	/* lire d'abord la file de message pour savoir si recepteur est le premier */
	/* processus lance, auquel cas                                             */
	/* il impose le mode d'ipc et le mode d'alarme (alarme ou timer)           */
	if ( (msqid = msgget (cle, IPC_CREAT|0660)) == -1 )
		ERREUR("msgget recepteur")
	
	/* obtenir les stats de la file de message pour savoir qui est le createur */
	/* et donc qui impose le mode d'ipc et le mode d'alarme (alarme ou timer)  */
	if ( msgctl (msqid, IPC_STAT, &md) == -1 )
		ERREUR("msgctl recepteur IPC_STAT")

	/* Est-ce qu'un message a deja ete envoye par un autre processus ? */
	if ( md.msg_lspid == 0 ) {
		RecepteurPremier = VRAI;
		/* Recepteur est le createur : il impose le mode d'ipc */
		if ( ModeIPC == NOIPC ) ModeIPC = MSG; /* forcer le mode d'IPC */
		/* preparer le message */
		message.mtype = MSGIPC;
		message.info  = ModeIPC;
		/* envoyer le message : mode d'IPC  */
		if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
			ERREUR("msgsnd recepteur MSGIPC")
	} else {
		/* Recepteur n'est pas le createur       */
		/* lire un autre message : mode d'ipc    */
		if ( msgrcv (msqid, &message, sizeof(message.info), MSGIPC, 0) == -1 )
			ERREUR("msgrcv recepteur MSGIPC")
		if ( ModeIPC == NOIPC )
			ModeIPC = message.info;
		else
			if ( ModeIPC != message.info ) {
				printf ("Recepteur n'est pas le createur, mode d'ipc deja donne    : %s\n", 
					(ModeIPC = message.info) == MSG ? "Message" : "Segment");
		}
	}

	switch (ModeIPC) {
	case MSG:
		if ( (msqid = msgget (cle, IPC_CREAT|0660)) == -1 )
			ERREUR("msgget recepteur")

		/* obtenir les stats de la liste d'ipc pour savoir qui est le createur */
		/* et donc qui impose le mode d'alarme (alarm ou timer)                */
		if ( msgctl (msqid, IPC_STAT, &md) == -1 )
			ERREUR("msgctl emetteur IPC_STAT")
	
		if ( RecepteurPremier ) {
		/* Recepteur est le createur : il impose le mode d'alarme */
		/* et la communique au recepteur                          */
			/* envoyer un message : mode d'alarme utilise   */
			if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
			/* preparer le message */
			message.mtype = MSGALRM;
			message.info  = ModeAlarme;
			/* envoyer le message : mode d'alarme */
			if ( msgsnd (msqid, &message, sizeof (message.info), 0) == -1 )
				ERREUR("msgsnd recepteur MSGALRM")
		} else {
		/* Recepteur n'est pas le createur */
		/* lire un message : mode d'alarme */
			if ( msgrcv (msqid, &message, sizeof(message.info), MSGALRM, 0) == -1 )
				ERREUR("msgrcv recepteur MSGALRM")
			if ( ModeAlarme == NOALRM )
				ModeAlarme = message.info;
			else
				if ( ModeAlarme != message.info )
					printf ("Recepteur n'est pas le createur, mode d'alarme deja donne : %s\n", 
						(ModeAlarme = message.info) == ALARM ? "ALARM": "TIMER");
		}	

		/* preparer le message */
		message.mtype = MSGPIDR;
		message.info  = getpid();
		/* envoyer le message : pid du recepteur */
		if (msgsnd (msqid, &message, sizeof (message.info), 0) == -1)
			ERREUR("msgsnd recepteur MSGPIDR")

		/* attente bloquante du pid de l'emetteur */
		if (msgrcv (msqid, &message, sizeof(message.info), MSGPIDE, 0) == -1)
			ERREUR("msgrcv recepteur")

		/* initialiser le pide en fonction du message recu */
		pide = message.info;
		break;

	case SHM:
		/* creer ou retrouver le segment de memoire partage et le mapper */
		if ( (shmid = shmget (cle, TAILLESHM, IPC_CREAT|0660)) == -1 )
			ERREUR("shmget recepteur")
		if ( (seg = (msgshm *) shmat(shmid, NULL, 0)) == NULL )
			ERREUR("shmat recepteur")
		if ( RecepteurPremier ) {
			/* Recepteur est le createur : il impose le mode d'alarme                  */
			/* et la communique a l'emetteur                                           */
			if ( ModeAlarme == NOALRM ) ModeAlarme = ALARM; /* forcer le mode d'alarme */
			seg->pidr = getpid();			/* ecrire le pid de l'emetteur              */
			seg->ModeAlrm = ModeAlarme;		/* imposer le mode d'alarme                 */
			while ( !(pide = seg->pide) );	/* attendre que le pid de l'emetteur        */
		} else {
			seg->pidr = getpid();			/* ecrire le pid du recepteur               */
			while ( !(pide = seg->pide) );	/* attendre que le pid de l'emetteur        */
			if ( ModeAlarme == NOALRM )
				ModeAlarme = seg->ModeAlrm;	/* lire le mode d'alarme du recepteur       */
			else
				if ( ModeAlarme != seg->ModeAlrm )
					printf ("Recepteur n'est pas le createur, mode d'alarme deja donne : %s\n", 
						(ModeAlarme = seg->ModeAlrm) == ALARM ? "ALARM" : "TIMER");
		}
		break;
	}

	/* message d'initialisation */
	printf ("Recepteur (pid = %-8d) : %s IPC et Mode %s\n", getpid(), 
		ModeIPC    == MSG ?   "Message" : "Segment",
		ModeAlarme == ALARM ? "ALARM"   : "TIMER");

	/* attente des signaux et de la terminaison de l'emetteur */
	while (1) pause();
}

#undef ERREUR


 Conclusion

Pour compiler :
make emetteur
make recepteur

ou utiliser le script mak (pour les feignants)

Pour tester :
emetteur [-options] &
recepteur [-option]

ou l'inverse, cela n'a pas d'importance puisque les processus se synchronisent.

Les options sont :
-a : utilisation d'une temporisation par la primitive alarm()
-t : utilisation d'une temporisation par la primitive setitimer()
-m : utilisation d'une file de message
-s : utilisation d'un segment de mémoire partagé

NB : il faut un système *NIX, l'implémentation des IPC sous cygwin étant incomplète.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

02 juin 2006 07:50:08 :
Ajout d'une note sur les signaux.

 Sources du même auteur

GÉNÉRATION D'UNE LISTE DES COMBINAISONS SANS RÉPÉTITION D'ÉL...
Source avec Zip SQUELETTE DE COMMUNICATION PAR SOCKET EN MODE CONNECTÉ POUR ...
TRI PAR INSERTION AVEC SENTINELLE
GÉNÉRATION D'UNE PERMUTATION ALÉATOIRE, SANS RETIRAGE

 Sources de la même categorie

Source avec Zip Source avec une capture INFORMATION PROCESSEUR (CPUID) par Devils_Tiger
Source avec Zip Source avec une capture LECTURE TEMPÉRATURE PROCESSEUR par Devils_Tiger
Source avec Zip Source avec une capture LECTURE FRÉQUENCE PROCESSEUR par Devils_Tiger
Source avec Zip Source avec une capture UNE LISTE HÉTÉROGÈNE DOUBLEMENT CHAINÉE par pgl10
Source avec Zip Source avec une capture POUR AFFICHER LES CARACTÈRES ACCENTUÉS SOUS WINDOWS EN MODE ... par pgl10

 Sources en rapport avec celle ci

Source avec Zip TRAITEMENT D'IMAGE PGM par Jios
Source avec une capture COLORIMÈTRE NUMÉRIQUE LINUX par valchek
Source avec Zip ORDONNANCEUR DE PROCESSUS par badrsmimite
Source avec Zip CALCULETTE EN C SOUS LINUX AVEC AUTOMATE SIMPLE par pch_hotline
Source avec Zip UNE APPLICATION CHAT, COMMUNICATION ENTRE DEUX PROCESSUS EN ... par Sofiane0

Commentaires et avis

Commentaire de ZedMaTrix le 01/06/2006 16:29:48

La vache, exellent ton code !

Moi qui voulais savoir comment fonctionne l'IPC, la je suis servis ! :)

Commentaire de AlexN le 02/06/2006 07:22:51

Merci,

Le code devait être simple pour être didactique. S'il a pu t'aider à comprendre ces mécanismes, j'en suis content. :o)

salut.

Commentaire de ZedMaTrix le 02/06/2006 16:04:45

Arf, pour le moment je ne l'ai pas encore étudié, juste survoler, car je lutte avec mes sockets et select() pour le moment.

Mais ensuite je me plongerai dans ta source !

Maintenant, elle n'est pas trés compliqué, ca va ! :P


Merci a toi !

Commentaire de tor_pen le 02/08/2006 17:58:22

Merci AlexN.
Fort util.

A++

Commentaire de AlexN le 17/08/2006 22:26:50

De rien.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

communication inter processus sous linux [ par boumarsel ] voila un processus cree un processus fils par fork, le fils execute un traitement (fonction) et retourne une valeur que je veux recuperer par le proce timer asynchrone [ par ToToL ] BonjourJ'ai besoin dans un programme en cour de création d'un timer asynchrone. je m'explique :j'ai besoin d'executer des actions a des heures bien pr temps d'exécution trop long [ par diable007 ] bonjour, j'ai une application parallèle en c++ et MPI,  j'ai une partie qui ne nécessite pas de communication avec mpi entre les processeurs.  En séqu L'événement est il un IPC ? [ par Booster ] Bonjour,Voila question à 300€ ^^ que je me suis posé, est ce que les évenements font partie de la catégorie IPC (Inter processus communication) ?Vu qu Communication Par TCP sous LINUX [ par Smeix ] Bonjour tout le monde je suis débutant en Linux ,je veux développer un script en mode TCP qui permet envoie d'un message à une adresse ip spécifié c question sur programmation linux [ par yolhaiji ] YOL.HAI.JIsalut:je voulais savoir comment sur linux peut on etablir une connexion entre un processus pere et ces deux processus fils avec les pipes ( processus sous linux [g++] [ par satanik_mike ] Bonjour,Je suis en train de d?velopper un serveur POP, SMTP en C++ sous linux, mais je bloque sur une petit probl?me d'ex?cution.J'ai fait un ex?cutbl le "kill(0,SIGTERM)" de Linux sous Win32 ? [ par Wulfaz ] je cherche une fonction C pour winNT & win98, équivalente à celle sous Linux/Unix : kill(0,SIGTERM). Pour ceux qui ne la connaisse pas elle envoie un [debutant] Interruption timer sous linux [ par PierrotLeCelte ] Bonjour,Je voudrais ecrire un petit programme ou une fonctionqui s'execute a chaque interruption de l'irq timer(irq = 0). D'abord est ce possible ? Et timer avec linux[?] [ par dmothes ] Help!!!quelqu'un pourrait-il m'aider? j'ai besoin d'utiliser un timer sous linux (si possible, en millisecondes)...faut-il utiliser linux/timer.h? com


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,858 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales