table of contents
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:
- sem_perm
- Jest to struktura ipc_perm (zob. niżej), która określa prawa dostępu do zestawu semaforów.
- sem_otime
- Czas ostatniego wywołania funkcji systemowej semop(2).
- sem_ctime
- Czas utworzenia zestawu semaforów albo czas ostatniej operacji IPCSET, SETVAL lub SETALL z SETVAL().
- sem_nsems
- 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:
- IPC_STAT
- 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.
- IPC_SET
- 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.
- IPC_RMID
- 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.
- IPC_INFO (specyficzne dla Linuksa)
- 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).
- SEM_INFO (specyficzne dla Linuksa)
- 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.
- SEM_STAT (specyficzne dla Linuksa)
- 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.
- SEM_STAT_ANY (specyficzne dla Linuksa, od Linuksa 4.17)
- 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).
- GETALL
- 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.
- GETNCNT
- 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.
- GETPID
- 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.
- GETVAL
- 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.
- GETZCNT
- 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.
- SETALL
- 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.
- SETVAL
- 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:
- GETNCNT
- wartość semncnt.
- GETPID
- wartość sempid.
- GETVAL
- wartość semval.
- GETZCNT
- wartość semzcnt.
- IPC_INFO
- 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).
- SEM_INFO
- tak jak IPC_INFO.
- SEM_STAT
- identyfikator zestawu semaforów, którego indeks został podany w semid.
- SEM_STAT_ANY
- 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¶
- EACCES
- 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.
- EFAULT
- Adres wskazywany przez arg.buf lub arg.array jest niedostępny.
- EIDRM
- Zestaw semaforów został usunięty.
- EINVAL
- 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.
- EPERM
- 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.
- ERANGE
- 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:
- SEMVMX
- 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 (niewydane) |