semop(2) System Calls Manual semop(2) NAZWA semop, semtimedop - operacje na semaforach Systemu V BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include int semop(int semid, struct sembuf *sops, size_t nsops); int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *_Nullable timeout); Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)): semtimedop(): _GNU_SOURCE OPIS Z kazdym semaforem w zestawie semaforow Systemu V sa skojarzone nastepujace wartosci: 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 modified the semaphore value */ semop() wykonuje operacje na wybranych semaforach z zestawu wskazywanego przez semid. Kazdy z nsops elementow tablicy wskazywanej przez parametr sops jest struktura okreslajaca operacje, ktora ma byc wykonana na pojedynczym semaforze. Struktura struct sembuf zawiera nastepujace pola: unsigned short sem_num; /* numer semafora */ short sem_op; /* operacja na semaforze */ short sem_flg; /* znaczniki operacji */ W sem_flg moga zostac ustawione znaczniki operacji: IPC_NOWAIT i SEM_UNDO. Jesli podano znaczniki SEM_UNDO, to operacja zostanie automatycznie cofnieta w chwili, gdy proces zakonczy dzialanie. Zestaw operacji zawartych w sops jest wykonywany w kolejnosci elementow tablicy oraz atomowo, co oznacza, ze operacje sa wykonywane albo w calosci, albo wcale. Zachowanie wywolania systemowego w sytuacji, gdy nie wszystkie operacje moga byc wykonane natychmiast, zalezy od ustawienia znacznika IPC_NOWAIT w poszczegolnych polach sem_flg, jak to opisano ponizej. Kazda z operacji jest wykonywana na semaforze o numerze sem_num w zestawie, przy czym pierwszy semafor ma numer 0. Sa trzy rodzaje operacji rozrozniane na podstawie wartosci sem_op. If sem_op is a positive integer, the operation adds this value to the semaphore value (semval). Furthermore, if SEM_UNDO is specified for this operation, the system subtracts the value sem_op from the semaphore adjustment (semadj) value for this semaphore. This operation can always proceed--it never forces a thread to wait. The calling process must have alter permission on the semaphore set. Jesli sem_op jest rowne 0, proces musi miec prawo do odczytu zestawu semaforow. Jest to operacja "oczekiwania na zero" (wait-for-zero): gdy semval ma wartosc 0, operacja moze byc kontynuowana bezzwlocznie. W przeciwnym razie, jesli w sem_flg przekazany zostal znacznik IPC_NOWAIT, wowczas semop() zglosi blad, zas zmienna errno przyjmie wartosc EAGAIN (i zadna z operacji z sops nie zostanie wykonana). Jezeli proces zostanie wstrzymany przez system, wowczas wartosc semzcnt (liczby watkow oczekujacych na osiagniecie przez semafor wartosci zero) zostanie zwiekszona o 1, a watek bedzie zawieszony az do chwili, gdy spelniony zostanie jeden z ponizszych warunkow: o semval osiagnie wartosc 0; wowczas wartosc pola semzcnt zostanie zmniejszona o 1. o Zestaw semaforow zostanie usuniety: semop() sie nie powiedzie i przypisze zmiennej errno wartosc EIDRM. o Watek wywolujacy funkcje przechwyci sygnal: wartosc semzcnt zostanie zmniejszona, a semop() zakonczy sie niepowodzeniem i przypisze zmiennej errno wartosc EINTR. Jesli sem_op ma wartosc mniejsza od 0, to proces musi miec prawo do modyfikacji zestawu semaforow. Jesli wowczas wartosc semafora semval jest wieksza lub rowna wartosci bezwzglednej sem_op, to operacja moze byc kontynuowana bezzwlocznie: wartosc semafora semval zostanie zmniejszona o wartosc bezwzgledna sem_op. Ponadto, jesli przekazano znacznik SEM_UNDO, to system dodaje calkowita wartosc sem_op do wartosci dopasowania (semadj) tego semafora. Jesli wartosc bezwzgledna sem_op jest wieksza niz semval, a w sem_flg przekazano znacznik IPC_NOWAIT, to semop() zakonczy sie niepomyslnie, przypisujac zmiennej errno wartosc EAGAIN (i zadna z operacji z sops nie zostanie wykonana). W przeciwnym wypadku semncnt (licznik watkow oczekujacych na zwiekszenie wartosci tego semafora) zostanie zwiekszony o 1, a watek nie zostanie wznowiony az do chwili wystapienia jednego z nastepujacych zdarzen: o semval staje sie wieksza lub rowna wartosci calkowitej sem_op: operacja przebiega teraz zgodnie z opisem powyzej. o Zestaw zostanie usuniety z systemu: semop() zwroci blad i ustawi zmienna errno na wartosc EIDRM. o Watek wywolujacy funkcje przechwyci sygnal: wartosc semncnt zostanie zmniejszona, a semop() zakonczy sie niepowodzeniem i przypisze zmiennej errno wartosc EINTR. Jesli operacja zostanie zakonczona pomyslnie, to wartosci sempid kazdego z semaforow wyszczegolnionych w tablicy wskazywanej przez sops przypisany zostanie identyfikator procesu (PID) wywolujacego. Ponadto polu sem_otime przypisany zostanie biezacy czas. semtimedop() semtimedop() zachowuje sie tak samo jak semop(), poza tym ze w tych przypadkach, gdy watek wywolujacy by spal, czas trwania spania jest ograniczony przez czas okreslony w strukturze timespec, ktorej adres jest przekazywany w parametrze timeout (interwal zostanie zaokraglony w gore do dokladnosci zegara, a wystepowanie opoznienia planisty jadra oznacza, ze ten interwal moze byc nieznacznie przekroczony). Jesli osiagnieto okreslony limit czasu, to semtimedop() zwraca blad, ustawiajac errno na EAGAIN (i zadna z operacji w sops nie jest wykonywana). Jezeli parametr timeout jest NULL, to semtimedop() zachowuje sie dokladnie 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. WARTOSC ZWRACANA On success, semop() and semtimedop() return 0. On failure, they return -1, and set errno to indicate the error. BLEDY E2BIG Wartosc nsops przekracza SEMOPM, maksymalna liczbe operacji wykonywanych w jednym wywolaniu. 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 moze byc natychmiast wykonana lub uplynal limit czasu okreslony w parametrze timeout. EFAULT Adres wskazywany przez parametr sops lub timeout jest niedostepny. EFBIG Numer semafora sem_num, do ktorego odnosi sie jedna z operacji, jest mniejszy od 0 albo wiekszy lub rowny liczbie semaforow w zestawie. EIDRM Zestaw semaforow zostal usuniety. EINTR Watek przechwycil sygnal podczas oczekiwania na odebranie komunikatu; patrz signal(7). EINVAL Zestaw semaforow nie istnieje lub wartosc semid jest mniejsza od zera, lub wartosc nsops nie jest liczba dodatnia. ENOMEM Znacznik SEM_UNDO zostal ustawiony w sem_flg dla pewnej operacji, a w systemie nie ma wystarczajacej ilosci pamieci na utworzenie nowej struktury do przechowywania informacji o zmianach. ERANGE Dla pewnej operacji wartosc sem_op+semval przekroczyla SEMVMX, czyli zalezna od implementacji maksymalna wartosc semval. STANDARDY POSIX.1-2008. WERSJE Linux 2.5.52 (backported into Linux 2.4.22), glibc 2.3.3. POSIX.1-2001, SVr4. UWAGI Struktury sem_undo nie sa dziedziczone przez dzieci tworzone za pomoca fork(2), ale sa dziedziczone przez wywolanie systemowe execve(2). semop() nie jest nigdy automatycznie uruchamiana ponownie po przerwaniu przez funkcje obslugi sygnalu, niezaleznie od ustawien znacznika SA_RESTART uzywanego podczas tworzenia funkcji obslugi sygnalu. A semaphore adjustment (semadj) value is a per-process, per-semaphore integer that is the negated sum of all operations performed on a semaphore specifying the SEM_UNDO flag. Each process has a list of semadj values--one value for each semaphore on which it has operated using SEM_UNDO. When a process terminates, each of its per-semaphore semadj values is added to the corresponding semaphore, thus undoing the effect of that process's operations on the semaphore (but see BUGS below). When a semaphore's value is directly set using the SETVAL or SETALL request to semctl(2), the corresponding semadj values in all processes are cleared. The clone(2) CLONE_SYSVSEM flag allows more than one process to share a semadj list; see clone(2) for details. Wartosci semval, sempid, semzcnt i semnct dla semafora mozna odczytac za pomoca odpowiednich wywolan semctl(2). Limity semaforow Wywolania semop() dotycza nastepujace ograniczenia zasobow zwiazanych z zestawami semaforow: 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 wartosc semval: zalezy od implementacji (32767). Implementacja w systemie Linux nie naklada wewnetrznych ograniczen na zmiane wartosci semafora podczas zakonczenia procesu (SEMAEM), na ogolnosystemowa maksymalna liczbe struktur przechowujacych informacje o zmianach stanu semaforow (SEMMNU), ani na maksymalna dla procesu liczbe struktur przechowujacych informacje o zmianach stanu semaforow. USTERKI Gdy proces konczy dzialanie, zestaw skojarzonych z nim struktur semadj jest wykorzystywany do cofniecia efektow wszystkich operacji na semaforach, ktore ten proces wykonal z ustawionym znacznikiem SEM_UNDO. Wprowadza to trudnosc: jezeli jedna (lub wiecej) sposrod tych zmian semaforow spowodowalby probe zmniejszenia wartosci semafora ponizej zera, to co implementacja powinna uczynic? Jednym z mozliwych podejsc do tego zadadnienia moglo by byc zablokowanie do chwili, gdy przeprowadzenie wszystkich zmian semaforow bedzie mozliwe. Jest to jednakze niepozadane, gdyz spowodowaloby wymuszenie zablokowania zakonczenia procesu na dowolnie dlugi okres. Inna mozliwoscia jest zignorowanie wszystkich takich zmian semaforow (nieco analogiczne do niepomyslnego zakonczenia, gdy dla operacji na semaforze podany jest znacznik IPC_NOWAIT). Linux przyjal trzecie rozwiazanie: zmniejszenie wartosci semafora na tyle, na ile jest to mozliwe (tzn. do zera) i umozliwienie natychmiastowej kontynuacji konczenia dzialania procesu. In Linux 2.6.x, x <= 10, there is a bug that in some circumstances prevents a thread that is waiting for a semaphore value to become zero from being woken up when the value does actually become zero. This bug is fixed in Linux 2.6.11. PRZYKLADY Nastepujacy fragment kodu uzywa semop() do atomowego oczekiwania na to, by wartosc semafora 0 doszla do zera. Nastepnie wartosc semafora jest zwiekszana 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 TAKZE clone(2), semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), sysvipc(7), time(7) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Rafal Lewczuk , Andrzej Krzysztofowicz , Robert Luberda i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.06 31 pazdziernika 2023 r. semop(2)