web-dev-qa-db-fra.com

implémentation de sémaphore

Je reçois une erreur dans le programme suivant. Je veux montrer comment deux processus peuvent partager une variable à l'aide de sémaphore. Quelqu'un peut-il me guider?

Je ne suis pas capable de déboguer les erreurs ...

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<semaphore.h>
int main()
{
  int pid,mutex=1;
  int semid;               /* semid of semaphore set */
  key_t key = 1234; /* key to pass to semget() */
  int nsems = 1; /* nsems to pass to semget() */
  semid=semget(key,nsems,IPC_CREAT|0666);
  if (semid<0) 
  { 
    perror("Semaphore creation failed ");
  }
  if ((pid = fork()) < 0) 
  {
    perror("fork");
    return 1;
  }
  else if(pid==0)
  {
    sem_wait(&semid);
    printf("IN CHILD PROCESS :\n");
    mutex++; 
    printf("value of shared variable =%d",mutex);
    sem_post(&semid);
    return 0;
  }
  sem_wait(&semid);
  printf("IN PARENT PROCESS :\n");
  mutex--;
  printf("value of shared variable =%d",mutex);
  sem_post(&semid);
  return 0;
} 
5
chinu

Vos principes fondamentaux sont incorrects, le programme ne fonctionnera pas, alors parcourez les bases et réécrivez le programme.

Certaines des corrections que vous devez faire sont les suivantes:

1) Vous devez créer une variable de type sémaphore

sem_t semvar;

2) Les fonctions sem_wait(), sem_post() nécessitent la variable sémaphore, mais vous transmettez l'id du sémaphore, ce qui n'a aucun sens.

sem_wait(&semvar);
   //your critical section code
sem_post(&semvar);

3) Vous passez le sémaphore à sem_wait() et sem_post() sans l'initialiser. Vous devez l'initialiser à 1 (dans votre cas) avant de l'utiliser, sinon vous aurez une impasse.

ret = semctl( semid, 1, SETVAL, sem);
if (ret == 1)
     perror("Semaphore failed to initialize");

Étudiez les API de sémaphore à partir de la page de manuel et suivez cet exemple exemple .

21
Barath Ravikumar

Le problème fondamental de votre code est que vous mélangez deux API. Malheureusement, les ressources en ligne ne sont pas très douées pour le signaler, mais il existe deux API de sémaphore sur les systèmes de type UNIX:

  • API POSIX IPC, qui est une API standard
  • API System V, issue de l'ancien monde Unix, mais pratiquement disponible sur presque tous les systèmes Unix

En regardant le code ci-dessus, vous avez utilisé semget () à partir de l'API System V et tenté de poster via sem_post (), qui provient de l'API POSIX. Il n'est pas possible de les mélanger.

Pour choisir l’API de sémaphore que vous voulez, vous n’avez pas autant de ressources de qualité. Le meilleur simple est la "Programmation réseau Unix" de Stevens. La section qui vous intéresse probablement est dans le Vol # 2.

Ces deux API sont étonnamment différentes. Les deux prennent en charge les sémaphores de style manuel, mais il convient de mentionner quelques points positifs et négatifs dans l'API System V:

  • il repose sur des ensembles de sémaphores, donc une fois que vous avez créé un objet avec semget (), il s'agit d'un ensemble de sémaphores plutôt que d'un seul
  • l'API System V vous permet d'effectuer des opérations atomiques sur ces ensembles. afin que vous puissiez modifier ou attendre plusieurs sémaphores dans un ensemble
  • l'API SysV vous permet d'attendre qu'un sémaphore atteigne un seuil plutôt que d'être différent de zéro. l'attente d'un seuil non nul est également prise en charge, mais ma phrase précédente implique que
  • les ressources de sémaphore sont assez limitées sur chaque unix. vous pouvez les vérifier avec la commande 'ipcs'
  • il existe une fonctionnalité d'annulation des sémaphores de System V, vous pouvez donc vous assurer que la fin anormale du programme ne laisse pas vos sémaphores dans un état indésirable
14
David Beck

Variez le taux de consommation et le taux de production (en utilisant le sommeil), afin de mieux comprendre le fonctionnement du code. Le code ci-dessous est la simulation consommateur-producteur (dépassant la limite maximale du conteneur).

Code pour votre référence:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

sem_t semP, semC;
int stock_count = 0;
const int stock_max_limit=5;

void *producer(void *arg) {
    int i, sum=0;
    for (i = 0; i < 10; i++) {

        while(stock_max_limit == stock_count){
            printf("stock overflow, production on wait..\n");
            sem_wait(&semC);
            printf("production operation continues..\n");
        }

        sleep(1);   //production decided here
        stock_count++;
        printf("P::stock-count : %d\n",stock_count);
        sem_post(&semP);
        printf("P::post signal..\n");
    }
 }

void *consumer(void *arg) {
    int i, sum=0;
    for (i = 0; i < 10; i++) {

        while(0 == stock_count){
            printf("stock empty, consumer on wait..\n");
            sem_wait(&semP);
            printf("consumer operation continues..\n");
        }

        sleep(2);   //consumer rate decided here
        stock_count--;
        printf("C::stock-count : %d\n", stock_count);
        sem_post(&semC);
        printf("C::post signal..\n");
        }
}

int main(void) {

    pthread_t tid0,tid1;
    sem_init(&semP, 0, 0);
    sem_init(&semC, 0, 0);

        pthread_create(&tid0, NULL, consumer, NULL);
        pthread_create(&tid1, NULL, producer, NULL);
        pthread_join(tid0, NULL);
        pthread_join(tid1, NULL);

    sem_destroy(&semC);
    sem_destroy(&semP);

    return 0;
}
3
parasrish

Veuillez vérifier cet exemple de code ci-dessous pour la mise en œuvre du sémaphore (verrouiller et déverrouiller).

    #include<stdio.h>
    #include<stdlib.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include<string.h>
    #include<malloc.h>
    #include <sys/sem.h>
    int main()
    {
            int key,share_id,num;
            char *data;
            int semid;
            struct sembuf sb={0,-1,0};
            key=ftok(".",'a');
            if(key == -1 ) {
                    printf("\n\n Initialization Falied of shared memory \n\n");
                    return 1;
            }
            share_id=shmget(key,1024,IPC_CREAT|0744);
            if(share_id == -1 ) {
                    printf("\n\n Error captured while share memory allocation\n\n");
                    return 1;
            }
            data=(char *)shmat(share_id,(void *)0,0);
            strcpy(data,"Testing string\n");
            if(!fork()) { //Child Porcess
                 sb.sem_op=-1; //Lock
                 semop(share_id,(struct sembuf *)&sb,1);

                 strncat(data,"feeding form child\n",20);

                 sb.sem_op=1;//Unlock
                 semop(share_id,(struct sembuf *)&sb,1);
                 _Exit(0);
            } else {     //Parent Process
              sb.sem_op=-1; //Lock
              semop(share_id,(struct sembuf *)&sb,1);

               strncat(data,"feeding form parent\n",20);

              sb.sem_op=1;//Unlock
              semop(share_id,(struct sembuf *)&sb,1);

            }
            return 0;
    }
1
Gyan Prakash