semctl(2) sterowanie semaforami Systemu V

SKŁADNIA

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>


int semctl(int semid, int semnum, int cmd, ...);

OPIS

semctl() wykonuje operację sterującą określoną przez cmd 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 cmd 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 ostatniej zmiany */
    unsigned long   sem_nsems; /* Liczba semaforów w zestawie */
};

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 */
};

Poprawne wartości parametru cmd 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
Zapisuje wartości niektórych pól struktury semid_ds wskazywanej przez arg.__buf do struktury danych jądra powiązanej z tym zestawem semaforów, aktualizując także pole sem_ctime. Następujące pola mogą być zmieniane: sem_perm.uid, sem_perm.gid oraz (9 najmniej znaczących bitów pola) sem_perm.mode. Efektywny identyfikator użytkownika procesu wywołującego musi być równy identyfikatorowi właściciela (sem_perm.uid) lub twórcy (sem_perm.cuid) segmentu pamięci dzielonej albo proces wywołujący musi być uprzywilejowany. Argument semnum jest ignorowany.
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.
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 numer semnum (tzn. liczbę procesów oczekujących na zwiększenie się wartości semval skojarzonej z semaforem numer semnum). 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 ostatnio wykonał semop(2) na semaforze o numerze semnum). Proces wywołujący musi mieć prawa do odczytu zestawu semaforów.
GETVAL
Zwraca wartość semval 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 o numerze semnum 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

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

W przeciwnym przypadku zwrócona zostanie nieujemna wartość zależna od parametru cmd:

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, 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.

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

BŁĘDY

Po niepomyślnym zakończeniu, zmienna errno przyjmie jedną z następujących wartości:
EACCES
Parametr cmd ma jedną z wartości GETALL, GETPID, GETVAL, GETNCNT, GETZCNT, IPC_STAT, SEM_STAT, SETALL lub SETVAL, a proces wywołujący nie ma wystarczających uprawnień do działania na zbiorze semaforów oraz nie ma ustawionego atrybutu CAP_IPC_OWNER.
EFAULT
Adres wskazywany przez arg.buf lub arg.array jest niedostępny.
EIDRM
Zestaw semaforów został usunięty.
EINVAL
Niepoprawna wartość parametru cmd 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 cmd 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 ustawionego atrybutu CAP_SYS_ADMIN.
ERANGE
Argument cmd 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.

ZGODNE Z

SVr4, POSIX.1-2001.

POSIX.1-2001 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.

UWAGI

Dołączenie <sys/types.h> i <sys/ipc.h> nie jest wymagane na Linuksie ani przez żadną z wersji POSIX. Jednak niektóre stare implementacje wymagają dołączenia tych plików nagłówkowych, SVID również dokumentuje ich dołączenie. Aplikacje które mają być przenośne na tego typu stare systemy mogą wymagać dołączenia omawianych plików nagłówkowych.

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.

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 cmd).

We wcześniejszych wersjach biblioteki glibc unia semun była zdefiniowana w <sys/sem.h>, jednakże POSIX.1-2001 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>.

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.

O STRONIE

Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem http://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Rafał Lewczuk (PTM) <[email protected]>, Andrzej Krzysztofowicz (PTM) <[email protected]>, Robert Luberda <[email protected]> i Michał Kułach <[email protected]>.

Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 3.71 oryginału.