next up previous contents
Next: WYWOŁANIE SYSTEMOWE: semctl() Up: Semafory Previous: WYWOŁANIE SYSTEMOWE: semget()   Contents

WYWOŁANIE SYSTEMOWE: semop()


     WYWOŁANIE SYSTEMOWE: semop();                                                          
     PROTOTYP: int semop ( int semid, struct sembuf *sops, unsigned nsops);
       ZWRACA: 0 - sukces ( przeprowadzono wszystkie operacje )
               -1 - błąd: errno = E2BIG ( nsops większy od maxymalnej liczby 
   	                               dozwolonych operacji atomowych )
                                  EACCESS ( brak prawa dostępu )
                                  EAGAIN ( IPC_NOWAIT ustawione, nie można 
   					przeprowadzić operacji )
                                  EFAULT ( nieprawidłowy adres wskazywany przez 
   					sops )
                                  EIDRM ( zestaw został usunięty )
                                  EINTR ( otrzymano sygnał w czasie spania )
                                  EINVAL ( zestaw nie istnieje lub nieprawidłowy semid )
   			       ENOMEM ( SEM_UNDO ustawione, brak pamięci aby utworzyć strukturę anulowania (undo) )
                                  ERANGE ( wartość semoforu poza zakresem )
     UWAGI:
   

Pierwszym argumentem dla semop() jest klucz ( w naszym przypadku zwrócony przez semget). Drugi argument (sops) jest wskaźnikiem do tablicy operacji , które mają zostać przeprowadzone na grupie semaforów. Trzeci argument (nsops) jest liczbą operacji w tablicy.

Argument sops wskazuje tablicę typu sembuf, który jest zdefiniowany w linux/sem.h:


           /* wywołanie systemowe semop bierze tablicę takich struktur */
           struct sembuf {
                   ushort  sem_num;        /* index semafora w tablicy */
                   short   sem_op;         /* opercja */
                   short   sem_flg;        /* flagi oparacji */
           };
   

sem_num

Numer semafora którym jesteś zainteresowany

sem_op

Operacja do wykonania ( dodatnia, ujemna lub zero )

sem_flg

Flagi operacji

Jeżeli sem_op jest ujemny jego wartość zostaje odjęta od semafora. Odpowiada to używaniu zasobów kontrolowanych lub monitorowanych przez semafor. Jeżeli nie podano IPC_NOWAIT proces wywołujący śpi do czasu aż wymagana liczba zasobów jest dostępna ( inny proces zwolnił jakieś ).

Jeżeli sem_op jest dodatni jego wartość jest dodawana do semafora. Odpowiada to zwolnieniu zasobów. Zasoby powinny być zawsze zwalniane jeżeli nie są dłużej używane!

Jeżeli sem_op jest zerem proces będzie spał do czasu aż semafor będzie miał wartość zera. Odpowiada to 100% użycia. Dobrym przykładem jest demon działający z prawami roota, który będzie dynamicznie zmieniał rozmiar zbioru semaforów jeżeli ten będzie w 100% użyty.

W celu wytłumaczenia wywołania semop przywołajmy nasz przykład z drukarkami. Załużmy, iż mamy tylko jedną drukarkę, która potrafi drukować tylko jedną pracę. Utworzymy zestaw tylko z jednym semaforem ( tylko jedna drukarka ) i zainicjujemy go wartością jeden ( tylko jedna praca ).

Za każdym razem gdy chcemy wysłać pracę do drukarki musimy upewnić się czy jest ona dostępna. Robimy to próbując otrzymać jedną jednostkę z semafora. Załadujmy tablicę sembuf aby tego dokonać:


           struct sembuf sem_lock = { 0, -1, IPC_NOWAIT };
   

Tak zainicjowana struktura wymusza dodanie -1 do semafora numer 0. Inaczej mówiąc jedna jednostka zasobu zostanie użyta z semafora numer 0. Podaliśmy IPC_NOWAIT, więc wywołanie natychmiast powróci lub zwróci błąd jeżeli ktoś używa naszą drukarkę. Oto przykład użycia zainicjowanej struktury sembuf:


           if((semop(sid, &sem_lock, 1) == -1)
                   perror("semop");
   

Trzeci argument (nsops) mówi, że wykonujemy tylko jedną operację ( mamy tylko jedną strukturę sembuf w naszej tablicy ). Argument sid jest identyfikatorem IPC naszego zestawu semaforów.

Po wydrukowaniu musimy oddać zasoby z powrotem do zestawu aby inni mogli wydrukować swoje prace.


           struct sembuf sem_unlock = { 0, 1, IPC_NOWAIT };
   

Taka struktura dyktuje dodanie 1 do semafora numer 0. Czyli: jedna jednostka zasobu powraca do zestawu.


next up previous contents
Next: WYWOŁANIE SYSTEMOWE: semctl() Up: Semafory Previous: WYWOŁANIE SYSTEMOWE: semget()   Contents

2000-03-01


Poltronic