Provided by: manpages-pl-dev_4.13-4_all bug

NAZWA

       semop, semtimedop - operacje na semaforach Systemu V

SKŁADNIA

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

       int semop(int semid, struct sembuf *sops, size_t nsops);

       int semtimedop(int semid, struct sembuf *sops, size_t nsops,
                      const struct timespec *timeout);

   Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

       semtimedop(): _GNU_SOURCE

OPIS

       Z każdym semaforem w zestawie semaforów Systemu V są skojarzone następujące wartości:

           unsigned short  semval;   /* semaphore value */
           unsigned short  semzcnt;  /* # waiting for zero */
           unsigned short  semncnt;  /* # waiting for increase */
           pid_t           sempid;   /* PID of process that last

       semop()  wykonuje  operacje  na  wybranych  semaforach  z zestawu wskazywanego przez semid. Każdy z nsops
       elementów tablicy wskazywanej przez parametr sops jest  strukturą  określającą  operację,  która  ma  być
       wykonana na pojedynczym semaforze. Struktura struct sembuf zawiera następujące pola:

           unsigned short sem_num;  /* numer semafora */
           short          sem_op;   /* operacja na semaforze */
           short          sem_flg;  /* znaczniki operacji */

       W  sem_flg  mogą  zostać  ustawione  znaczniki  operacji:  IPC_NOWAIT  i SEM_UNDO. Jeśli podano znaczniki
       SEM_UNDO, to operacja zostanie automatycznie cofnięta w chwili, gdy proces zakończy działanie.

       Zestaw operacji zawartych w sops jest wykonywany w kolejności elementów tablicy oraz atomowo, co oznacza,
       że operacje są wykonywane albo w całości, albo wcale. Zachowanie wywołania systemowego  w  sytuacji,  gdy
       nie  wszystkie  operacje  mogą  być  wykonane  natychmiast,  zależy  od ustawienia znacznika IPC_NOWAIT w
       poszczególnych polach sem_flg, jak to opisano poniżej.

       Każda z operacji jest wykonywana na semaforze o numerze sem_num w zestawie, przy czym pierwszy semafor ma
       numer 0. Są trzy rodzaje operacji rozróżniane na podstawie wartości sem_op.

       Jeśli sem_op jest liczbą dodatnią, to wartość semafora (semval) zostanie zwiększona o tę liczbę.  Ponadto
       jeśli  przekazano  znacznik SEM_UNDO, to system odejmuje wartość (semop) od wartości dopasowania (semadj)
       tego semafora. Operacja ta zawsze może być wykonana —  nigdy  nie  spowoduje  wstrzymania  wątku.  Proces
       wywołujący funkcję musi mieć prawo do modyfikacji zestawu semaforów.

       Jeśli  sem_op  jest  równe  0,  proces  musi  mieć  prawo  do odczytu zestawu semaforów. Jest to operacja
       "oczekiwania na  zero"  (wait-for-zero):  gdy  semval  ma  wartość  0,  operacja  może  być  kontynuowana
       bezzwłocznie.  W przeciwnym razie, jeśli w sem_flg przekazany został znacznik IPC_NOWAIT, wówczas semop()
       zgłosi błąd, zaś zmienna errno przyjmie wartość EAGAIN (i żadna z operacji z sops nie zostanie wykonana).
       Jeżeli proces zostanie wstrzymany przez system, wówczas wartość semzcnt (liczby  wątków  oczekujących  na
       osiągnięcie przez semafor wartości zero) zostanie zwiększona o 1, a wątek będzie zawieszony aż do chwili,
       gdy spełniony zostanie jeden z poniższych warunków:

       • semval osiągnie wartość 0; wówczas wartość pola semzcnt zostanie zmniejszona o 1.

       • Zestaw semaforów zostanie usunięty: semop() się nie powiedzie i przypisze zmiennej errno wartość EIDRM.

       • Wątek  wywołujący  funkcję  przechwyci sygnał: wartość semzcnt zostanie zmniejszona, a semop() zakończy
         się niepowodzeniem i przypisze zmiennej errno wartość EINTR.

       Jeśli sem_op ma wartość mniejszą od 0, to proces musi mieć prawo do modyfikacji zestawu semaforów.  Jeśli
       wówczas wartość semafora semval jest większa lub równa wartości bezwzględnej sem_op, to operacja może być
       kontynuowana  bezzwłocznie:  wartość  semafora  semval zostanie zmniejszona o wartość bezwzględną sem_op.
       Ponadto, jeśli przekazano znacznik SEM_UNDO, to  system  dodaje  całkowitą  wartość  sem_op  do  wartości
       dopasowania (semadj) tego semafora. Jeśli wartość bezwzględna sem_op jest większa niż semval, a w sem_flg
       przekazano  znacznik IPC_NOWAIT, to semop() zakończy się niepomyślnie, przypisując zmiennej errno wartość
       EAGAIN (i żadna z operacji z sops nie zostanie wykonana). W przeciwnym wypadku  semncnt  (licznik  wątków
       oczekujących  na  zwiększenie  wartości  tego  semafora)   zostanie  zwiększony o 1, a wątek nie zostanie
       wznowiony aż do chwili wystąpienia jednego z następujących zdarzeń:

       • semval staje się większa lub równa wartości całkowitej  sem_op:  operacja  przebiega  teraz  zgodnie  z
         opisem powyżej.

       • Zestaw zostanie usunięty z systemu: semop() zwróci błąd i ustawi zmienną errno na wartość EIDRM.

       • Wątek  wywołujący  funkcję  przechwyci sygnał: wartość semncnt zostanie zmniejszona, a semop() zakończy
         się niepowodzeniem i przypisze zmiennej errno wartość EINTR.

       Jeśli operacja zostanie zakończona pomyślnie, to wartości sempid każdego z semaforów wyszczególnionych  w
       tablicy wskazywanej przez sops przypisany zostanie identyfikator procesu (PID) wywołującego. Ponadto polu
       sem_otime przypisany zostanie bieżący czas.

   semtimedop()
       semtimedop()  zachowuje się tak samo jak semop(), poza tym że w tych przypadkach, gdy wątek wywołujący by
       spał, czas trwania spania jest ograniczony przez czas określony w strukturze timespec, której adres  jest
       przekazywany  w  parametrze  timeout  (interwał  zostanie  zaokrąglony  w  górę  do dokładności zegara, a
       występowanie opóźnienia planisty jądra oznacza, że ten interwał może być nieznacznie przekroczony). Jeśli
       osiągnięto określony limit czasu, to semtimedop() zwraca błąd, ustawiając errno  na  EAGAIN  (i  żadna  z
       operacji  w  sops  nie jest wykonywana). Jeżeli parametr timeout jest NULL, to semtimedop() zachowuje się
       dokładnie tak samo jak semop().

       Note that if semtimedop()  is interrupted by a signal, causing the call to fail with the error EINTR, the
       contents of timeout are left unchanged.

WARTOŚĆ ZWRACANA

       semop() i semtimedop zwracają 0, jeśli zakończą  się  pomyślnie.  W  przeciwnym  wypadku  zwracają  -1  i
       przypisują zmiennej errno wartość wskazującą na rodzaj błędu.

BŁĘDY

       W przypadku wystąpienia błędu, zmiennej errno przypisywana jest jedna z następujących wartości:

       E2BIG  Wartość nsops przekracza SEMOPM, maksymalną liczbę operacji wykonywanych w jednym wywołaniu.

       EACCES The  calling  process  does  not  have the permissions required to perform the specified semaphore
              operations, and does not have the CAP_IPC_OWNER capability in the user namespace that governs  its
              IPC namespace.

       EAGAIN Operacja  opatrzona znacznikiem IPC_NOWAIT w sem_flg nie może być natychmiast wykonana lub upłynął
              limit czasu określony w parametrze timeout.

       EFAULT Adres wskazywany przez parametr sops lub timeout jest niedostępny.

       EFBIG  Numer semafora sem_num, do którego odnosi się jedna z operacji, jest mniejszy od  0  albo  większy
              lub równy liczbie semaforów w zestawie.

       EIDRM  Zestaw semaforów został usunięty.

       EINTR  Wątek przechwycił sygnał podczas oczekiwania na odebranie komunikatu; patrz signal(7).

       EINVAL Zestaw  semaforów nie istnieje lub wartość semid jest mniejsza od zera, lub wartość nsops nie jest
              liczbą dodatnią.

       ENOMEM Znacznik  SEM_UNDO  został  ustawiony  w  sem_flg  dla  pewnej  operacji,  a  w  systemie  nie  ma
              wystarczającej  ilości  pamięci  na  utworzenie  nowej  struktury  do  przechowywania informacji o
              zmianach.

       ERANGE Dla pewnej operacji wartość sem_op+semval przekroczyła  SEMVMX,  czyli  zależną  od  implementacji
              maksymalną wartość semval.

WERSJE

       semtimedop()   po  raz  pierwszy  pojawiło  się w Linuksie 2.5.52, ale zostało przeniesione (backport) do
       jądra 2.4.22. Biblioteka glibc obsługuje semtimedop() od wersji 2.3.3.

ZGODNE Z

       POSIX.1-2001, POSIX.1-2008, SVr4.

UWAGI

       Dołączenie <sys/types.h> i <sys/ipc.h> nie jest wymagane na Linuksie ani  przez  żadną  z  wersji  POSIX.
       Jednak   niektóre  stare  implementacje  wymagają  dołączenia  tych  plików  nagłówkowych,  SVID  również
       dokumentuje ich dołączenie. Aplikacje które mają być przenośne na tego typu stare  systemy  mogą  wymagać
       dołączenia omawianych plików nagłówkowych.

       Struktury sem_undo nie są dziedziczone przez dzieci tworzone za pomocą fork(2), ale są dziedziczone przez
       wywołanie systemowe execve(2).

       semop()  nie  jest  nigdy automatycznie uruchamiana ponownie po przerwaniu przez funkcję obsługi sygnału,
       niezależnie od ustawień znacznika SA_RESTART używanego podczas tworzenia funkcji obsługi sygnału.

       Wartość dopasowania semafora (semadj) jest przypisana do  procesu  i  semafora  i  jest  sumą  wszystkich
       operacji na semaforze z flagą SEM_UNDO, ze znakiem przeciwnym. Każdy proces ma listę wartości semadj - po
       jednej  dla  każdego  semafora na której operuje za pomocą SEM_UNDO. Gdy proces się kończy wszystkie jego
       wartości semadj przypisane do poszczególnych semaforów są do  nich  dodawane,  co  powoduje  przywrócenie
       wartości  semafora  sprzed  działania procesu (zob. jednak na BŁĘDY). Gdy wartość semafora jest ustawiane
       bezpośrednio za pomocą żądań SETVAL  lub  SETALL  do  semctl(2),  to  odpowiadające  wartości  semadj  we
       wszystkich  procesach są czyszczone. Flaga CLONE_SYSVSEM clone(2) pozwala to dzielenie listy semadj przez
       więcej niż jeden proces, więcej szczegółów w podręczniku clone(2).

       Wartości semval, sempid, semzcnt i semnct dla semafora można  odczytać  za  pomocą  odpowiednich  wywołań
       semctl(2).

   Limity semaforów
       Wywołania semop() dotyczą następujące ograniczenia zasobów związanych z zestawami semaforów:

       SEMOPM Maximum  number of operations allowed for one semop()  call.  Before Linux 3.19, the default value
              for this limit was 32.  Since Linux 3.19, the default value is 500.  On Linux, this limit  can  be
              read  and  modified  via  the third field of /proc/sys/kernel/sem.  Note: this limit should not be
              raised above 1000, because of the risk of that semop()  fails due to kernel  memory  fragmentation
              when allocating memory to copy the sops array.

       SEMVMX Maksymalna dozwolona wartość semval: zależy od implementacji (32767).

       Implementacja  w  systemie  Linux nie nakłada wewnętrznych ograniczeń na zmianę wartości semafora podczas
       zakończenia procesu (SEMAEM), na ogólnosystemową maksymalną liczbę struktur przechowujących informacje  o
       zmianach  stanu  semaforów  (SEMMNU),  ani  na  maksymalną  dla  procesu  liczbę struktur przechowujących
       informacje o zmianach stanu semaforów.

BŁĘDY

       Gdy proces kończy działanie, zestaw skojarzonych z nim struktur semadj jest wykorzystywany  do  cofnięcia
       efektów  wszystkich  operacji  na semaforach, które ten proces wykonał z ustawionym znacznikiem SEM_UNDO.
       Wprowadza to trudność: jeżeli  jedna  (lub  więcej)  spośród  tych  zmian  semaforów  spowodowałby  próbę
       zmniejszenia  wartości  semafora  poniżej  zera,  to co implementacja powinna uczynić? Jednym z możliwych
       podejść do tego zadadnienia mogło by być zablokowanie do chwili,  gdy  przeprowadzenie  wszystkich  zmian
       semaforów  będzie  możliwe.   Jest  to  jednakże  niepożądane, gdyż spowodowałoby wymuszenie zablokowania
       zakończenia procesu na dowolnie długi okres.  Inną możliwością jest zignorowanie wszystkich takich  zmian
       semaforów  (nieco  analogiczne  do  niepomyślnego  zakończenia, gdy dla operacji na semaforze podany jest
       znacznik IPC_NOWAIT).  Linux przyjął trzecie rozwiązanie: zmniejszenie wartości semafora na tyle, na  ile
       jest to możliwe (tzn. do zera) i umożliwienie natychmiastowej kontynuacji kończenia działania procesu.

       Jądra 2.6.x, gdzie x <= 10, zawierają błąd, który w pewnych okolicznościach spowoduje, że wątek czekający
       na  zmniejszenie  wartości  semafora  do zera nie zostanie obudzony, gdy ta wartość rzeczywiście osiągnie
       zero. Błąd został poprawiony w jądrze 2.6.11.

PRZYKŁADY

       Następujący fragment kodu używa semop() do atomowego oczekiwania na to, by wartość semafora 0  doszła  do
       zera. Następnie wartość semafora jest zwiększana o jeden.

           struct sembuf sops[2];
           int semid;

           /* Code to set semid omitted */

           sops[0].sem_num = 0;        /* Operate on semaphore 0 */
           sops[0].sem_op = 0;         /* Wait for value to equal 0 */
           sops[0].sem_flg = 0;

           sops[1].sem_num = 0;        /* Operate on semaphore 0 */
           sops[1].sem_op = 1;         /* Increment value by one */
           sops[1].sem_flg = 0;

           if (semop(semid, sops, 2) == -1) {
               perror("semop");
               exit(EXIT_FAILURE);
           }

       A further example of the use of semop()  can be found in shmop(2).

ZOBACZ TAKŻE

       clone(2), semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), sysvipc(7), time(7)

O STRONIE

       Angielska  wersja  tej strony pochodzi z wydania 5.10 projektu Linux man-pages. Opis projektu, informacje
       dotyczące   zgłaszania   błędów   oraz   najnowszą   wersję   oryginału   można   znaleźć   pod   adresem
       https://www.kernel.org/doc/man-pages/.

T◈UMACZENIE

       Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Rafał Lewczuk <R.Lewczuk@elka.pw.edu.p>,
       Andrzej  Krzysztofowicz  <ankry@green.mf.pg.gda.pl>,  Robert  Luberda <robert@debian.org> i Michał Kułach
       <michal.kulach@gmail.com>

       Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje  o  warunkach  licencji  można  uzyskać
       zapoznając   się   z   GNU General Public License w wersji 3   lub  nowszej.  Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

       Błędy w  tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej  manpages-pl-
       list@lists.sourceforge.net.

Linux                                          11 kwietnia 2020 r.                                      SEMOP(2)