Tux

Unix : Programmation Système

TD 6 - Les IPC

C. Drocourt
I.U.T. Amiens
drocourt@iut-amiens.fr

Le but de ce TD est simplement de se familiariser avec le fonctionnement des IPC, pour cela vous allez étudier les trois exemples de programmes suivants associés à chaque type d'IPC.

Exercice 1 : Les sémaphores

/* Programme 1 IPC - semaphore - processus createur */

#include <stdio.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>

int main()
{
  key_t cle;
  struct sembuf operation;
  int semid;


  if((cle = ftok(".",12)) == -1) {
   fprintf(stderr,"Probleme de cle\n");
   exit(2);
  }

  if((semid=semget(cle, 1, IPC_CREAT|IPC_EXCL|0600)) == -1)
  {
    perror("\nErreur de création de sémpahore");
    exit(1);
  }

  /* Initialisation du sémaphore à 0 */
  semctl(semid,0,SETVAL,0);

  printf("Je suis la tache 1 et je suis en section critique pendant 5 secondes ... \n");
  sleep(5);
  printf("T1 : Fin de section critique, operation V sur le semaphore ...\n");
  operation.sem_num=0;
  operation.sem_op=1;
  operation.sem_flg=0;
  if (semop(semid,&operation,1)==-1)  {
    perror("\nImpossible de décrémenter le sémaphore");
    exit(3);
  }
  printf("Fin de T1\n");
  exit(0);
}
/* Programme 2 IPC - semaphore - processus destructeur */

#include <stdio.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>

int main()
{
  key_t cle;
  struct sembuf operation;
  int semid;


  if((cle = ftok(".",12)) == -1) {
   fprintf(stderr,"Probleme de cle\n");
   exit(2);
  }

  if((semid=semget(cle,1,0))==-1)
  {
    perror("\nErreur de création de sémpahore");
    exit(1);
  }

  /* Initialisation du sémaphore à 0 */

  printf("Je suis la tache 2 et j'attend le semaphore ... \n");
  operation.sem_num=0;
  operation.sem_op=-1;
  operation.sem_flg=0;
  if (semop(semid,&operation,1)==-1)  {
    perror("\nImpossible de décrémenter le sémaphore");
    exit(3);
  }
  printf("Je suis la tache 2 et je peux rentrer en section critique ... \n");
  sleep(5);
  printf("Fin de T2\n");
  semctl(semid,0,IPC_RMID);
  exit(0);

Exercice 2 : Les segments de mémoire partagée

/* prod.c */
 
/*
  ce programme lit une suite de nombres, et effectue
  le cumul dans une variable en memoire partagee.
*/
 
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
 
struct donnees {
  int nb;
  int total;
};
 
int main(void) 
{
  key_t cle;
  int id;
  struct donnees *commun;
  int reponse;
 
  cle = ftok(".",'A'); 
  if (cle==-1) {
    perror("ftok");
    exit(EXIT_FAILURE);
  };
  id = shmget(cle,
              sizeof(struct donnees),
              IPC_CREAT | IPC_EXCL | 0666);
  if (id == -1) {
    switch(errno) {
      case EEXIST :
        fprintf(stderr,"Le segment existe d?j?\n");
        break;
      default:
        perror("shmget"); 
        break;
    }
    exit(EXIT_FAILURE);
  };
  commun = (struct donnees *)shmat (id,NULL,SHM_R | SHM_W);
  if (commun == NULL) {
    perror("shmat");
    exit(EXIT_FAILURE);
  };
 
  commun->nb    = 0;
  commun->total = 0;
 
  while(1)
  {
    printf("+ ");
    if (scanf("%d",&reponse)!=1) break;
    commun->nb++;
    commun->total += reponse;
    printf("sous-total %d= %d\n",commun->nb,commun->total);
  };
  printf("---\n");
  if (shmdt((char *)commun) == -1) {
    perror("shmdt");
    exit(EXIT_FAILURE);
  };
  /* suppression segment */
  if (shmctl(id,IPC_RMID,NULL) == -1) {
    perror("shmctl(remove)");
    exit(EXIT_FAILURE);
  };
  exit(EXIT_SUCCESS);
}

/* cons.c */
 
/*
   Ce programme affiche le contenu de la memoire partagee
   Arret par Contrele-C
*/
 
/* 
   fonctionne seulement si prod et cons sont lances 
   dans le meme repertoire (voir ftok(".",'A')).
*/
 
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
 
struct donnees {
  int nb;
  int total;
};
 
int encore;
 
void arret(int signal)
{
  encore=0;
}
 
int main(void) 
{
  key_t cle;
  int id;
  struct donnees *commun;
  struct sigaction a;
 
  cle = ftok(".",'A');
  if (cle==-1) {perror("ftok"); exit(EXIT_FAILURE);};
  id = shmget(cle,sizeof(struct donnees),0);
 
  if (id == -1) {  
    switch(errno) {
      case ENOENT:
        printf("pas de segment\n");
        exit(EXIT_SUCCESS);
      default:
        perror("shmget"); 
        exit(EXIT_FAILURE);
    };
  };
  commun = (struct donnees *)shmat (id,NULL,SHM_R);
  if (commun == NULL) {
    perror("shmat");
    exit(EXIT_FAILURE);
  };
 
  encore = 1;
 
  a.sa_handler = arret;
  sigemptyset(&a.sa_mask); 
  a.sa_flags = 0;
  sigaction(SIGINT,&a,NULL);
 
  while(encore)
  {
    sleep(2);
    printf("sous-total %d= %d\n",commun->nb,commun->total);
  };
 
  printf("---\n");
  if ( shmdt((char *)commun) == -1) {
    perror("shmdt");
    exit(EXIT_FAILURE);
  };
  exit(EXIT_SUCCESS);
}

Exercice 3 : Les files de messages

/* rcv.c */

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

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

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

#define MAXTEXTE 1000
struct tampon {
  long mtype;
  char mtext[MAXTEXTE];
};

int id,encore=1;

void arret(int signal)
{
  encore=0;
  msgctl(id,IPC_RMID,NULL);
}

int main(int argc,char *argv[])
{
  int cle;
  struct sigaction a;

  if (argc!=2) {
    fprintf(stderr,"Usage: %s cle\n", argv[0]);
    exit(1);
  };
  cle = atoi(argv[1]);
  id  = msgget (cle,IPC_CREAT | 0666);
  if (id == -1)
  {
    perror("msgget");
    exit(EXIT_FAILURE);
  };

  a.sa_handler = arret;
  sigemptyset(&a.sa_mask);
  a.sa_flags = 0;
  sigaction(SIGINT,&a,NULL);

  while(encore) {
    int l;
    struct tampon msg;
    l = msgrcv(id,(struct msgbuf *)&msg,MAXTEXTE,0L,0);
    if(l == -1)
    {
      perror("msgrcv");
      exit(EXIT_FAILURE);
    };
    printf("(type=%ld) %s\n",msg.mtype,msg.mtext);
  };
  exit(EXIT_SUCCESS);
}
/* snd.c */

/*
   envoi des messages dans une file (IPC System V)
*/

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

#define MAXTEXTE 1000
struct tampon {
  long mtype;    
  char mtext[MAXTEXTE]; 
};

int main(int argc,char *argv[])
{
  int cle,id, mtype;
  if (argc!=3) {
    fprintf(stderr,"Usage: %s cle type\n", argv[0]);
    exit(1);
  };
  cle  = atoi(argv[1]);
  mtype= atoi(argv[2]);
  id   = msgget (cle,0666);
  if (id==-1) {
    perror("msgget");
    exit(EXIT_FAILURE);
  };

  while(1) {
    int l;
    struct tampon msg;
    printf("> ");
    fgets(msg.mtext, MAXTEXTE, stdin);
    l = strlen(msg.mtext);
    msg.mtype = mtype;
    if (msgsnd(id,(struct msgbuf *)&msg,l+1,0) == -1)
    {
      perror("msgsnd");
      exit(EXIT_FAILURE);
    };
  };
}