Syncronisations Problem



  • Hallo Leute ich habe eine Problem meine Prozesse zu Syncronisieren.

    Ich möchte folgendes erreichen
    ein Prozess der auf meine Queue lesen und schreiben kann
    eine unbestimmte anzahl von Prozessen die auf die Queue schreiben kann
    desweiteren soll der Prozess der lesen und schreiben kann sollange warten
    bis wieder was auf der Queue ist!!
    dabei kann ich nur 2 Semaphoren verwenden!!

    ich habe ne Funktion
    Lock(semid);
    und eine Funktion
    Unlock(semid);

    wie kriege ich das hin
    ich stehe derzeitig voll auf dem Schlauch



  • Warum kann der eine lesen und schreiben?



  • Folgendes soll erreicht werden

    Prozess(1..n)
    push_data();//natürlich auch syncronisiert

    HauptProzess
    read_data();
    pop_data();

    und jetzt weiss ich leider nicht wie ich das syncronisieren soll

    ich kann leider nur 2 Semaphoren verwenden

    Bitte um hilfe



  • Ist die Aufgabenstellung irgendwie online?



  • Ist keine Aufgabenstellung für die Uni oder Schule, ist für ein privates Projekt

    So ich versuche mich mal verständlicher auszudrücken

    Ich will folgendes erreichen:

    HauptProzess soll von einer Queue Daten lesen.
    Solange keine Daten auf der Queue sind soll er warten.
    Falls Daten auf die Queue geschrieben werden soll der Hauptprozess mit der Abarbeitung der Daten in der Queue beginnen.
    Falls weitere Prozesse in der Zeit, in der der Hauptprozess die Daten liest auf die Queue schreiben will sollen diese Prozesse warten.

    Was ich aus Datenbanktechnischen Gründen leider nur machen kann sind 2 Semaphoren für diese Synchronisation zu verwenden.



  • Zunächst benötigst du einen Semaphor, um zu verhindern, daß sich die Prozesse gegenseitig unterbrechen - jeder Prozess reserviert ihn, wenn er arbeiten will, und gibt ihn am Ende wieder frei. Den zweiten Semaphor kannst du verwenden, um das leere-Liste-Problem zu lösen (obwohl da Events geeigneter wären) - die Schreib-Prozesse geben ihn jeweils frei, wenn sie fertig sind mit Einfügen, der Hauptprozess sperrt ihn und wartet dann auf die Freigabe, wenn er die Liste geleert hat.



  • So ich habe mir mal ein Programm dazu geschrieben
    es Funktioniert nicht da irgendwie nur ein Prozess zum Printf kommt
    und alle anderen warten brauche hilfe

    #include <sys/sem.h>
    #include <sys/ipc.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #define LOCK  -1
    #define UNLOCK 1
    #define KEY1  123458L
    #define KEY2  123459L
    #define PERM  0666
    
    int sem_id1;
    int sem_id2;
    
    static int init_semaphore (long key)
     {
       /* Testen ob das Semaphor bereits existiert */
      int semid;
       semid = semget (key, 0, IPC_PRIVATE);
       if (semid < 0) {
          /* ... existiert noch nicht also anlegen */
          /* Alle Zugriffsrechte der Dateikreierungsmaske erlauben */
          umask(0);
          semid = semget (key, 1, IPC_CREAT | IPC_EXCL | PERM);
          if (semid < 0) {
             printf ("Fehler beim Anlegen des Semaphors ...\n");
             return -1;
          }
          printf ("(angelegt) Semaphor-ID : %d\n", semid);
          /* Semaphor mit 1 initialisieren */
          if (semctl (semid, 0, SETVAL, (int) 1) == -1)
             return -1;
       }
       return semid;
    }
    
    static int sem_op (int op,int sem)
     {
    static struct sembuf semaphore;
       semaphore.sem_op = op;
       semaphore.sem_flg = SEM_UNDO;
       if( semop (sem, &semaphore, 1) == -1) {
          perror(" semop ");
          printf("HALLO\n");
          exit (EXIT_FAILURE);
       }
       return 1;
    }
    
    int main()
    {
      int a =0;
      sem_id1 =init_semaphore(KEY1);
      sem_id2 =init_semaphore(KEY2);
    
      if(fork== NULL)
        {
          sem_op(LOCK,sem_id1);
          printf("%d,push_dat\n",getpid());
          sem_op(UNLOCK,sem_id1);
          sem_op(UNLOCK,sem_id2);
        }
    
      if(fork == NULL)
        {
          sem_op(LOCK,sem_id1);
          printf("%d,push_dat\n",getpid());
          sem_op(UNLOCK,sem_id1);
          sem_op(UNLOCK,sem_id2);
        }
    
      if(fork == NULL)
        {
         sem_op(LOCK,sem_id1);
         printf("%d,push_dat\n",getpid());
         sem_op(UNLOCK,sem_id1);
         sem_op(UNLOCK,sem_id2);
        }
    
      while(a <100)
        {
          sem_op(LOCK,sem_id1);
    
          sem_op(LOCK,sem_id2);
          printf("%d,read_data()\n",getpid());
          sem_op(UNLOCK,sem_id1);
          a++;
        }
    
      semctl (sem_id1, 0, IPC_RMID, 0);
      semctl (sem_id2, 0, IPC_RMID, 0);
      return 0;
    }
    


  • Hier mal ein wenig pseudocode:

    2 Semaphoren "datenVorhanden" und "datenLeer". "datenVorhanen" wird auf 0 initialisiert, "datenLeer" auf 1.

    Leserprozess:

    while(1)
    {
      semwait(datenVorhanden); // warte, daß die Semaphore 1 wird
      verarbeiteDaten();
      sempost(datenLeer); // setze Sem auf 1
    }
    

    Schreiber:

    while(1)
    {
      semwait(datenLeer); // warte, daß Semaphore 1 wird
      schreibeDaten();
      sempost(datenVoranden); // melde Leser, daß Daten da sind
    }
    

    Schreiberprozesse können beliebig viele vorhanden sein, da nur einer die Semaphore "datenLeer" dekrementieren kann.

    Tntnet



  • Hallo habe immer noch das gleiche Problem ich hoffe ich die Vorgeschlagen Implementierung richtig hingekriegt
    aber leider funktioniert das immer noch nicht
    denn Mein Prog geht in kein printf rein

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/types.h>
    #include <errno.h>
    #include <sys/sem.h>
    
    static struct sembuf semaphore;
    
    #define Lock    -1
    #define Unlock 1
    
    long CreateKey(int a)
    {
    		return ftok("/usr/include",a);
    
    }
    int pbCreateSemaphore(long key,int init)
    {
    		static int a = 0;
    		int sem_id;
    		a++;		
    
    		sem_id = semget(CreateKey(a )+getpid(),1,IPC_PRIVATE);
    		if (sem_id  < 0)
    		{
    				umask(0);
    				sem_id = semget(CreateKey( key)+getpid(),1,IPC_CREAT |  IPC_EXCL | 0666);
    				if(sem_id < 0)
    				{
    						printf("%s\n",strerror(errno));
    						return -1;
    				}
    
    				if(semctl(sem_id,0,SETVAL,(int)init)== -1)
    				{
    				       printf("%s:\n",strerror(errno));
    						return -1;  
    				}
    		} 
    
    		return sem_id; 
    }
    
    void pbCloseSemaphore(int sem)
    {
    		semctl(sem,0,IPC_RMID,0);
    }
    
    void pbSemaphoreOperation(int sem,int oper)
    {
    
    		semaphore.sem_op = oper;
    		semaphore.sem_flg = SEM_UNDO;
    
    		if(semop(sem,&semaphore,1) == -1)
    		{
    
    				exit(-1);
    		}
    
    }
    
    void semwait(int sem)
    {
           pbSemaphoreOperation(sem,Unlock);
    }
    void sempost(int sem)
    {
           pbSemaphoreOperation(sem,Unlock);
    }
    int main(int argc, char *argv[])
    {
           int semid1;
           int semid2;
           int a = 0;
    
           semid1 = pbCreateSemaphore(777,0);
           semid2 = pbCreateSemaphore(888,1);
    
           if(fork == 0)
           {
    	      while(1)
    	      {
    		     pbSemaphoreOperation(semid2,Lock);
    		     printf("push_data:%d\n",getpid());
    		     pbSemaphoreOperation(semid1,Unlock);
    		     pbSemaphoreOperation(semid2,Unlock);
    	      }
           }
           if(fork == 0)
           {
    	      while(1)
    	      {
    		     pbSemaphoreOperation(semid2,Lock);
    		     printf("push_data:%d\n",getpid());
    		     pbSemaphoreOperation(semid1,Unlock);
    		     pbSemaphoreOperation(semid2,Unlock);
    	      }
           }
           if(fork == 0)
           {
    	      while(1)
    	      {
    		     pbSemaphoreOperation(semid2,Lock);
    		     printf("push_data:%d\n",getpid());
    		     pbSemaphoreOperation(semid1,Unlock);
    	      }
           }
    
           while (a < 100)
           {
    	      pbSemaphoreOperation(semid1,Lock);
    	      pbSemaphoreOperation(semid2,Lock);
    	      printf("read_data:%d\n",getpid());
    
    	      sleep(1);
    	      pbSemaphoreOperation(semid2,Unlock);
    	      a++;
           }
    
           pbCloseSemaphore(semid1);
           pbCloseSemaphore(semid2);
      return EXIT_SUCCESS;
    }
    


  • Ich weiß nicht, ob Du meine Antwort gelesen hast, aber es sieht nicht so aus. Dein Programm sieht mehr wie rumprobieren aus, bis es funktioniert, als wirklich verstehen.

    Wobei mir auffällt, daß du gar keine Subprozesse startest. Der code:

    if(fork == 0)
    

    bewirkt, daß der Rumpf dann ausgeführt wird, wenn die Funktion fork ein Nullpointer ist. Das ist aber sich nicht der Fall. Du willst offensichtilch die Funktion fork aufrufen. Das macht man so:

    if (fork())
    

    Wobei Du damit noch keine Fehlerbehandlung hast. Fork könnte einen Fehlercode liefern. Den solltest Du auf jeden Fall abfragen.

    Tntnet



  • Sorry ich bin ein Trottelkind
    fork() ich weiss ich bin blöd meine Fresse

    ich versuche es nochmal


Anmelden zum Antworten