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; /* wartosc semafora */ unsigned short semzcnt; /* liczba oczekujacych na zero */ unsigned short semncnt; /* liczba oczekujacych na zwiekszenie */ pid_t sempid; /* PID procesu, ktory jako ostatni zmodyfikowal wartosc semafora */ 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. Jesli sem_op jest liczba dodatnia, to wartosc semafora (semval) zostanie zwiekszona o te liczbe. Ponadto jesli przekazano znacznik SEM_UNDO, to system odejmuje wartosc (semop) od wartosci dopasowania (semadj) tego semafora. Operacja ta zawsze moze byc wykonana -- nigdy nie spowoduje wstrzymania watku. Proces wywolujacy funkcje musi miec prawo do modyfikacji zestawu semaforow. 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(). Prosze zauwazyc, ze jesli semtimedop() zostanie przerwane przez sygnal, co spowoduje niepomyslne zakonczenie wywolania z bledem EINTR, zawartosc timeout pozostanie bez zmian. WARTOSC ZWRACANA semop() i semtimedop zwracaja 0, jesli zakoncza sie pomyslnie. W przypadku bledu zwracaja -1 i ustawiaja errno wskazujac blad. BLEDY E2BIG Wartosc nsops przekracza SEMOPM, maksymalna liczbe operacji wykonywanych w jednym wywolaniu. EACCES Proces wywolujacy nie ma wystarczajacych uprawnien do wykonania podanych operacji na semaforach oraz nie ma ustawionego przywileju CAP_IPC_OWNER (ang. capability) w przestrzeni nazw uzytkownika, ktora zarzadza jego przestrzenia nazw IPC. 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-2024. HISTORIA semop() SVr4, POSIX.1-2001. semtimedop() SVr4, Linux 2.5.52 (przeniesione rowniez na Linuksa 2.4.22), glibc 2.3.3. 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. Wartosc dopasowania semafora (semadj) jest przypisana do procesu i semafora i jest suma wszystkich operacji na semaforze z flaga SEM_UNDO, ze znakiem przeciwnym. Kazdy proces ma liste wartosci semadj -- po jednej dla kazdego semafora na ktorej operuje za pomoca SEM_UNDO. Gdy proces sie konczy wszystkie jego wartosci semadj przypisane do poszczegolnych semaforow sa do nich dodawane, co powoduje przywrocenie wartosci semafora sprzed dzialania procesu (zob. jednak na USTERKI). Gdy wartosc semafora jest ustawiane bezposrednio za pomoca zadan SETVAL lub SETALL do semctl(2), to odpowiadajace wartosci semadj we wszystkich procesach sa czyszczone. Flaga CLONE_SYSVSEM clone(2) pozwala to dzielenie listy semadj przez wiecej niz jeden proces, wiecej szczegolow w podreczniku clone(2). 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 Maksymalna liczba dozwolonych operacji na jedno wywolanie semop(). Przed Linuksem 3.19 domyslna wartosc tego limitu wynosila 32. Od Linuksa 3.19 jest to 500. Pod Linuksem, limit ten mozna odczytac i zmodyfikowac w trzecim polu pliku /proc/sys/kernel/sem. Uwaga: limit ten nie powinien wynosic ponad 1000, poniewaz istnieje ryzyko, ze semop() nie powiedzie sie z powodu fragmentacji pamieci jadra przy przydzielaniu pamieci dla kopii tablicy sops. 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. Linux 2.6.x, gdzie x <= 10, zawieraja blad, ktory w pewnych okolicznosciach spowoduje, ze watek czekajacy na zmniejszenie wartosci semafora do zera nie zostanie obudzony, gdy ta wartosc rzeczywiscie osiagnie zero. Blad zostal poprawiony w Linuksie 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; /* Pomieto kod sluzacy do ustawienia semid */ sops[0].sem_num = 0; /* Dzialanie na semaforze 0 */ sops[0].sem_op = 0; /* Oczekiwanie na przyjecie wartosci 0 */ sops[0].sem_flg = 0; sops[1].sem_num = 0; /* Dzialanie na semaforze 0 */ sops[1].sem_op = 1; /* Zwiekszenie wartosci o jeden */ sops[1].sem_flg = 0; if (semop(semid, sops, 2) == -1) { perror("semop"); exit(EXIT_FAILURE); } Kolejny przyklad uzycia semop() znajduje sie w podreczniku shmop(2). ZOBACZ TAKZE clone(2), semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), sysvipc(7), time(7) TLUMACZENIE Tlumaczenie niniejszej strony podrecznika: 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.17 8 lutego 2026 r. semop(2)