Problem bei Prozesssynchronisation mit POSIX-Semaphoren unter SUSE 8.1



  • Ich schreibe ein Programm, dass zwei Prozesse unter Linux startet. Diese enthalten kritische Bereiche, die gegeneinander abgesichert sein sollen.

    Dazu erstelle ich einen Semaphor mit

    semid = semget(IPC_PRIVATE, 1, IPC_CREAT|0777);
    

    Dann bereite ich die Semaphor-Operationen vor:

    sem_p[0].sem_num = 0;
    sem_v[0].sem_num = 0;
    sem_p[0].sem_op = 1;
    sem_v[0].sem_op = -1;
    

    Danach erstelle ich mit fork() zwei Kindprozesse. Diese müssten dann ja die Semaphoren enthalten.

    Nun möchte ich die kritischen Bereiche in den Kindprozessen absichern:

    kindprozess()
    {
       semop(semid, sem_p, 1);
    
       //Kritischer Bereich
    
       semop(semid, sem_v, 1);
    }
    

    Aber die kritischen Bereiche der beiden Kindprozesse überlagern sich trotzdem. Wo liegt mein Fehler?



  • Uh, ich hab lange nichts mehr mit Semaphoren gemacht, aber den Beispiel Code hab ich noch rumfliegen, vielleicht hilft er dir

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/sem.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int id;
    struct sembuf semaphor;
    
    void critical() { printf("CRITICAL %d\n",getpid()); }
    
    void lock() {
      semaphor.sem_op=-1;
      semaphor.sem_num=0;
      semaphor.sem_flg=SEM_UNDO;
    
      if(semop(id,&semaphor,1)==-1) {
        perror("semop");
        exit(1);
      }
    }
    
    void unlock() {
      semaphor.sem_op=1;
      semaphor.sem_num=0;
      semaphor.sem_flg=SEM_UNDO;
    
      if(semop(id,&semaphor,1)==-1) {
        perror("semop");
        exit(1);
      }
    }
    
    void child() {
      for(;;) {
        lock();
        critical();
        unlock();
      }
    }
    
    pid_t make_child() {
      pid_t pid=fork();
    
      if(pid==-1) {
        perror("fork");
        exit(1);
      }
      else if(!pid)
        child();
      else
        return pid;
      return 0;
    }
    
    int main() {
      id=semget(IPC_PRIVATE,1,IPC_CREAT|IPC_EXCL |S_IRWXU|S_IRWXG|S_IRWXO);
      if(id==-1) {
        perror("semget");
        return 1;
      }
    
      semctl(id,0,SETALL);
    
      make_child();
      make_child();
    
      int status;
      wait(&status);
      wait(&status);
      return 0;
    }
    


  • Erstmal Danke für die schnelle Antwort.

    Aber es funktioniert nicht. Zuerst habe ich deine Variante in meinen Code eingebaut ... das ging nicht. Dann habe ich dein komplettes Beispiel 1:1 übernommen und das funktioniert auch nicht. Es kommt gar keine Ausgabe.

    Ich habe in die lock()-Methode eine printf()-Ausgabe eingebaut. Diese zeigt, dass beide Prozesse in die Methode lock() gehen. Aber nach semop(id, &semaphor, 1) rührt sich gar nichts mehr.

    Könnte das vielleicht mit meinem SuSe 8.1 zusammenhängen?



  • Ich habe jetzt herausgefunden warum dein Beispielcode nicht funktioniert. Wenn man ein Semaphorenset anlegt, dann werden die Semaphoren darin standardmäßig mit 0 (also belegt) initialisiert. Also muss man nach semget schon eine erste Operation, die den Semaphor hochzählt, ausführen.


Anmelden zum Antworten