Scroll to navigation

semctl(2) System Calls Manual semctl(2)

NAZWA

semctl - steruje semaforami Systemu V

BIBLIOTEKA

Standardowa biblioteka C (libc, -lc)

SKŁADNIA

#include <sys/sem.h>
int semctl(int semid, int semnum, int op, ...);

OPIS

semctl() wykonuje operację sterującą, określoną przez op, na zestawie semaforów Systemu V określonym przez semid lub na semaforze o numerze semnum z tego zestawu (numeracja semaforów w zestawie semaforów zaczyna się od 0).

W zależności od op funkcja przyjmuje trzy lub cztery argumenty. Jeśli są cztery, to czwarty jest typu union semun. Program wywołujący musi zdefiniować tę unię jako:


union semun {

int val; /* Wartość dla SETVAL */
struct semid_ds *buf; /* Bufor dla IPC_STAT, IPC_SET */
unsigned short *array; /* Tablica dla GETALL, SETALL */
struct seminfo *__buf; /* Bufor dla IPC_INFO
(specyficzne dla Linuksa) */ };

Struktura danych semid_ds jest zdefiniowana w <sys/sem.h> następująco:


struct semid_ds {

struct ipc_perm sem_perm; /* Prawa dostępu */
time_t sem_otime; /* Czas ostatniej operacji semop */
time_t sem_ctime; /* Czas utworzenia/ostatniej zmiany
za pomocą semctl() */
unsigned long sem_nsems; /* Liczba semaforów w zestawie */ };

Pola struktury semid_ds są następujące:

Jest to struktura ipc_perm (zob. niżej), która określa prawa dostępu do zestawu semaforów.
Czas ostatniego wywołania funkcji systemowej semop(2).
Czas utworzenia zestawu semaforów albo czas ostatniej operacji IPCSET, SETVAL lub SETALL z SETVAL().
Liczba semaforów w zestawie. Każdy semafor zestawu jest identyfikowany przez nieujemną liczbę całkowitą z zakresu od 0 do sem_nsems-1.

Struktura ipc_perm jest zdefiniowana następująco (wyróżnione pola można ustawić za pomocą IPC_SET):


struct ipc_perm {

key_t __key; /* Klucz podany w semget(2) */
uid_t uid; /* Efektywny UID właściciela */
gid_t gid; /* Efektywny GID właściciela */
uid_t cuid; /* Efektywny UID twórcy */
gid_t cgid; /* Efektywny GID twórcy */
unsigned short mode; /* Uprawnienia */
unsigned short __seq; /* Numer sekwencji */ };

Najmniej znaczące 9 bitów pola mode struktury ipc_perm definiuje uprawnienia dostępu do segmentu pamięci dzielonej. Istnieją następujące bity uprawnień:

0400 Odczyt przez użytkownika
0200 Zapis przez użytkownika
0040 Odczyt przez grupę
0020 Zapis przez grupę
0004 Odczyt przez pozostałych
0002 Zapis przez pozostałych

Dla zestawu semaforów „zapis” znaczy w praktyce „modyfikację”. Bity 0100, 0010 i 0001 (bity praw do uruchamiania) nie są przez system wykorzystywane.

Poprawne wartości parametru op to:

Kopiuje informacje ze struktury kontrolnej jądra skojarzonej z semid do struktury semid_ds wskazywanej przez arg.__buf. Argument semnum jest ignorowany. Wywołujący musi mieć uprawnienie odczytu zestawu semaforów.
Zapis wartości niektórych pól struktury semid_ds wskazywanej przez parametr arg.buf do struktury kontrolnej zestawu semaforów. Pole sem_ctime zostanie automatycznie uaktualnione.
Zaktualizowane mogą również zostać następujące pola tej struktury: sem_perm.uid, sem_perm.gid i (9 najmniej znaczących bitów z) sem_perm.mode.
Efektywny identyfikator użytkownika procesu wywołującego musi odpowiadać właścicielowi (sem_perm.uid) lub twórcy (sem_perm.cuid) zestawu semaforów albo wywołujący musi być uprzywilejowany. Argument semnum jest pomijany.
Usuwa natychmiast zestaw semaforów. Wznawia wszystkie procesy zablokowane w wywołaniu semop(2) (wywołanie to zasygnalizuje błąd i ustawi zmienną errno na EIDRM). Efektywny identyfikator użytkownika procesu wywołującego musi odpowiadać twórcy lub właścicielowi zestawu semaforów albo proces wywołujący musi być uprzywilejowany. Argument semnum jest pomijany.
Zwraca w strukturze, na którą wskazuje arg.__buf, informacje o systemowych ograniczeniach i parametrach semaforów. Struktura jest typu seminfo i jest zdefiniowana w <sys/shm.h>, pod warunkiem, że zdefiniowano również makro _GNU_SOURCE:

struct  seminfo {

int semmap; /* Liczba wpisów w mapie semaforów
nieużywane przez jądro */
int semmni; /* Maksymalna liczba zestawów semaforów */
int semmns; /* Maksymalna liczba semaforów we wszystkich
zestawach semaforów */
int semmnu; /* Maksymalna liczba struktur wycofania (undo)
w systemie; nieużywane przez jądro*/
int semmsl; /* Maksymalna liczba semaforów
w zestawie */
int semopm; /* Maksymalna liczba operacji dla
semop(2) */
int semume; /* Maksymalna liczba wpisów wycofania (undo)
procesu; nieużywane przez jądro */
int semusz; /* Rozmiar struktury sem_undo */
int semvmx; /* Maksymalna wartość semafora */
int semaem; /* Maksymalna wartość możliwa do zapamiętania
dla regulacji semafora (SEM_UNDO) */ };

Ustawienia semmsl, semmns, semopm oraz semmni można zmienić za pomocą plików w /proc/sys/kernel/sem; szczegóły można znaleźć w podręczniku proc(5).
Zwraca strukturę seminfo zawierającą te same informacje co w przypadku IPC_INFO, z tym wyjątkiem, że w następujących polach zwracane są informacje o zasobach systemowych wykorzystywanych przez semafory: pole semusz zwraca liczbę zestawów semaforów istniejących obecnie w systemie; pole semaem zwraca całkowitą liczbę semaforów we wszystkich zestawach semaforów w systemie.
Zwraca strukturę semid_ds, taką jak dla IPC_STAT. Jednakże parametr semid nie jest identyfikatorem segmentu, ale indeksem wewnętrznej tablicy jądra przechowującej informacje o wszystkich segmentach zestawach semaforów w systemie.
Zwraca strukturę semid_ds, jak dla SEM_STAT. Jednak sem_perm.mode nie jest sprawdzany pod kątem uprawnień odczytu do semid co oznacza, że każdy użytkownik może wykonać tę operację (podobnie jak każdy użytkownik może odczytać /proc/sysvipc/sem, pozyskując te same informacje).
Zwraca (bieżącą) wartość semval dla wszystkich semaforów z zestawu, umieszczając je w tablicy arg.array. Argument semnum jest pomijany. Proces wywołujący musi mieć prawa do odczytu zestawu semaforów.
Zwraca wartość semncnt skojarzoną z semaforem o numerze semnum w zestawie (tzn. liczbę procesów oczekujących na zwiększenie wartości przez semafor). Proces wywołujący musi mieć prawa do odczytu zestawu semaforów.
Zwraca wartość sempid skojarzoną z semaforem o numerze semnum w zestawie. Jest to identyfikator procesu, który wykonał ostatnią operację na tym semaforze (ale zob. UWAGI). Proces wywołujący musi mieć prawa do odczytu zestawu semaforów.
Zwraca semval (tj. wartość semafora) semafora o numerze semnum w zestawie semaforów. Proces wywołujący musi mieć prawa do odczytu zestawu semaforów.
Zwraca wartość semzcnt skojarzoną z semaforem o numerze semnum w zestawie (tzn. liczbę procesów oczekujących na osiągnięcie przez semafor wartości 0). Proces wywołujący musi mieć prawa do odczytu zestawu semaforów.
Przypisuje wartości semval wszystkim semaforom zestawu, korzystając z tablicy arg.array, jednocześnie aktualizuje pole sem_ctime struktury semid_ds skojarzonej z zestawem. Wpisy wycofania (undo; patrz semop(2)) są czyszczone dla wszystkich zmienianych semaforów we wszystkich procesach. Jeżeli zmiany wartości semaforów pozwoliłyby na odblokowanie procesów oczekujących w wywołaniach semop(2), to te procesy są wznawiane. Argument semnum jest pomijany. Proces wywołujący musi mieć prawa do modyfikacji (zapisu) zestawu semaforów.
Przypisuje wartość semval do arg.val semafora o numerze semnum w zestawie, aktualizując jednocześnie pole sem_ctime struktury semid_ds skojarzonej z zestawem semaforów. Wpisy wycofania (undo) są czyszczone dla zmienianych semaforów we wszystkich procesach. Jeżeli zmiany wartości semaforów pozwoliłyby na odblokowanie procesów oczekujących w wywołaniach semop(2), to te procesy są wznawiane. Proces wywołujący funkcję musi mieć prawa do modyfikacji zestawu semaforów.

WARTOŚĆ ZWRACANA

Po pomyślnym zakończeniu, semctl() zwraca nieujemną wartość zależną od parametru op:

wartość semncnt.
wartość sempid.
wartość semval.
wartość semzcnt.
indeks najwyższego używanego wpisu w wewnętrznej tablicy jądra przechowującej informacje o wszystkich zestawach semaforów (informacji tej można użyć w operacjach SEM_STAT lub SEM_STAT_ANY, aby otrzymać informacje o wszystkich zestawach semaforów w systemie).
tak jak IPC_INFO.
identyfikator zestawu semaforów, którego indeks został podany w semid.
tak jak SEM_STAT.

Dla wszystkich pozostałych wartości op w razie pomyślnego zakończenia zwracane jest 0.

W razie błędu semctl() zwraca -1, a zmiennej errno zostanie nadana wartość określająca rodzaj błędu.

BŁĘDY

Argument op ma jedną z wartości: GETALL, GETPID, GETVAL, GETNCNT, GETZCNT, IPC_STAT, SEM_STAT, SEM_STAT_ANY, SETALL, lub SETVAL, a proces wywołujący nie ma wystarczających uprawnień do działania na zbiorze semaforów oraz nie ma ustawionego przywileju CAP_IPC_OWNER (ang. capability) w przestrzeni nazw użytkownika, która zarządza jego przestrzenią nazw IPC.
Adres wskazywany przez arg.buf lub arg.array jest niedostępny.
Zestaw semaforów został usunięty.
Niepoprawna wartość parametru op lub semid. Albo: w przypadku operacji SEM_STAT wartość indeksu podana w parametrze semid odwoływała się do obecnie nieużywanego elementu tablicy.
Parametr op jest równy IPC_SET lub IPC_RMID, ale identyfikator efektywnego użytkownika procesu wywołującego nie jest twórcą (określonym w sem_perm.cuid) ani właścicielem (określonym w sem_perm.uid) zestawu semaforów, a proces nie ma przywileju CAP_SYS_ADMIN.
Argument op ma wartość SETALL lub SETVAL, ale przekazywana wartość semafora semval (dla któregoś z semaforów zestawu) jest mniejsza od 0 lub większa od wartości ograniczenia systemowego SEMVMX.

WERSJE

POSIX.1 określa pole sem_nsems struktury semid_ds jako będące typu unsigned short i tak też jest ono zdefiniowane w większości systemów. Tak było również w Linuksie 2.2 i wcześniejszych, lecz od Linuksa 2.4 pole to jest typu unsigned long.

Wartość sempid

POSIX.1 definiuje sempid jako "identyfikator procesu ostatniej operacji" na semaforze i wprost zauważa, że wartość tak jest ustawiana przez pomyślne wywołanie semop(2), z implikacją, że żaden inny interfejs nie wpływa na wartość sempid.

Choć niektóre implementacje są zgodne z zachowaniem opisanym w POSIX.1, to inne nie są (błąd prawdopodobnie leży tu w specyfikacji POSIX.1, jako że nie zauważyła ona tylu przykładów istniejących implementacji). Różne inne implementacje aktualizują sempid również przy innych operacjach aktualizujących wartość semafora: operacjach SETVAL i SETALL, jak również dostosowaniach semafora wykonywanych przy zakończeniu procesu jako konsekwencji użycia flagi SEM_UNDO (zob. semop(2)).

Linux aktualizuje sempid również przy operacjach SETVAL i dostosowaniach semafora. Jednak, nieco niekonsekwentnie, do wersji Linuksa 4.5 włącznie, jądro nie aktualizowało sempid przy operacjach SETALL. Skorygowano to w Linuksie 4.6.

STANDARDY

POSIX.1-2008.

HISTORIA

POSIX.1-2001, SVr4.

Niektóre pola struktury struct semid_ds były w Linuksie 2.2 typu short, ale stały się typu long w Linuksie 2.4. Aby to wykorzystać, powinna wystarczyć rekompilacja pod glibc-2.1.91 lub nowszą. (Jądro rozróżnia stare wywołania od nowych za pomocą znacznika IPC_64 w op).

We wcześniejszych wersjach biblioteki glibc unia semun była zdefiniowana w <sys/sem.h>, jednakże POSIX.1 wymaga, żeby to program wywołujący definiował tę unię. Wersje glibc, które nie definiują tej unii, definiują makro _SEM_SEMUN_UNDEFINED w <sys/sem.h>.

UWAGI

Operacje IPC_INFO, SEM_STAT oraz SEM_INFO są używane przez program ipcs(1) w celu dostarczenia informacji o zajmowanych zasobach. W przyszłości operacje te mogą zostać zmodyfikowane lub przeniesione do interfejsu systemu plików /proc.

Na wywołanie semctl() wpływa następujące ograniczenie systemowe dotyczące zbioru semaforów:

Maksymalna wartość semval: zależna od implementacji (32767).

W celu uzyskania lepszej przenośności, najlepiej zawsze wywoływać semctl() z czterema argumentami.

PRZYKŁADY

Zobacz shmop(2).

ZOBACZ TAKŻE

ipc(2), semget(2), semop(2), capabilities(7), sem_overview(7), sysvipc(7)

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.

2 maja 2024 r. Linux man-pages 6.8