Provided by: manpages-pl-dev_4.15.0-9_all bug

NAZWA

       semop, semtimedop - operacje na semaforach Systemu V

SKŁADNIA

       #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

       On success, semop()  and semtimedop()  return 0.  On failure,  they  return  -1,  and  set
       errno to indicate the error.

BŁĘDY

       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

       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.13  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
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   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⟩.