Provided by:
manpages-pl-dev_20060617-1_all 
NAZWA
semop, semtimedop - operacje na semaforach
SKŁADNIA
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct
timespec *timeout);
OPIS
Semafor jest reprezentowany za pomocą anonimowej struktury zawierającej
następujące pola:
unsigned short semval; /* wartość semafora */
unsigned short semzcnt; /* # oczekiwanie na zero */
unsigned short semncnt; /* # oczekiwanie na zwiększenie */
pid_t sempid; /* proces, który wykonał ost. op. */
Funkcja semop wykonuje operacje na wybranych semaforach z zestawu
wskazywanego przez semid. Każdy z nsops elementów tablicy wskazywanej
przez parametr sops określa operację, która ma być wykonana na
semaforze. Struktura struct sembuf zawiera następujące pola:
unsigned short sem_num; /* numer semafora */
short sem_op; /* operacja na semaforze */
short sem_flg; /* dodatkowe znaczniki operacji */
W sem_flg mogą zostać ustawione znaczniki operacji: IPC_NOWAIT i
SEM_UNDO. Jeśli operacja jest opatrzona znacznikiem SEM_UNDO, to
zostanie cofnięta w chwili, gdy proces zakończy działanie.
Zestaw operacji zawartych w sops jest wykonywany atomowo, to znaczy,
operacje są wykonywane jednocześnie i tylko wtedy, gdy wszystkie mogą
być jednocześnie wykonywane. Zachowanie funkcji systemowej w sytuacji,
gdy nie wszystkie operacje mogą być wykonane natychmiast, zależy od
ustawienia znacznika IPC_NOWAIT w poszczególnych polach sem_flg, jak to
opisano poniżej.
Każda z nich jest wykonywana na sem_num-tym semaforze w zestawie, przy
czym pierwszy semafor ma numer 0. Istnieją trzy rodzaje operacji,
rozróżniane na podstawie wartości sem_op.
Jeśli sem_op jest liczbą dodatnią, to wartość semafora (semval)
zostanie zwiększona o tę liczbę. Ponadto, jeśli został przekazany
znacznik SEM_UNDO, wówczas system zaktualizuje licznik zmian (semadj)
tego semafora dla procesu Operacja ta nigdy nie powoduje wstrzymania
procesu. Proces wywołujący funkcję musi mieć prawo do modyfikacji
zestawu semaforów.
Jeśli sem_op jest równe 0, proces musi mieć prawo do odczytu zestawu
semaforów. Jest to operacja "oczekiwania na zero" (wait-for-zero): gdy
semval ma wartość 0, operacja może być kontynuowana bezzwłocznie. W
przeciwnym razie, jeśli w sem_flg przekazany został znacznik
IPC_NOWAIT, wówczas funkcja systemowa zgłosi błąd, zaś zmienna errno
przyjmie wartość EAGAIN (i żadna z operacji z sops nie zostanie
wykonana). Jeśli proces zostanie wstrzymany przez system, wówczas
wartość semzcnt (liczby procesów oczekujących na osiągnięcie przez
semafor wartości zero) zostanie zwiększona o 1. Proces będzie
zawieszony aż do chwili, gdy spełniony zostanie jeden z poniższych
warunków:
o semval osiągnie wartość 0; wówczas wartość pola semzcnt zostanie
zmniejszona o 1.
o Zestaw semaforów zostanie usunięty: system zgłosi błąd,
przypisując zmiennej errno wartość EIDRM.
o Proces wywołujący funkcję przechwyci sygnał: wartość semzcnt
zostanie zmniejszona o 1, natomiast system zgłosi błąd,
przypisując zmiennej errno wartość EINTR.
Jeśli sem_op ma wartość mniejszą od 0, to proces musi mieć prawo do
modyfikacji zestawu semaforów. Jeśli wówczas wartość semafora semval
jest większa lub równa wartości bezwzględnej sem_op, to operacja może
być kontynuowana bezzwłocznie: wartość semafora semval zostanie
zmniejszona o wartość bezwzględną sem_op. Ponadto, jeśli przekazano
znacznik SEM_UNDO, wówczas system zaktualizuje licznik zmian semafora
dla procesu (semadj). Jeśli wartość bezwzględna sem_op jest większa
niż semval, a w sem_flg przekazano znacznik IPC_NOWAIT, system zgłosi
błąd przypisując zmiennej errno wartość EAGAIN (i żadna z operacji z
sops nie zostanie wykonana). W przeciwnym wypadku semncnt (licznik
procesów oczekujących na zwiększenie wartości tego semafora) zostanie
zwiększony o 1. Proces może być wznowiony w następujących sytuacjach:
o semval osiągnie wartość większą lub równą wartości bezwzględnej
sem_op; wtedy wartość semncnt zostanie zmniejszona o 1, zaś
wartość bezwzględna z sem_op zostanie odjęta od semval . Jeśli
przekazany został znacznik SEM_UNDO , to system zaktualizuje
licznik zmian semafora dla procesu (semadj).
o Zestaw zostanie usunięty z systemu: funkcja systemowa zgłosi
błąd, przypisując zmiennej errno wartość EIDRM.
o Proces wywołujący funkcję przechwyci sygnał: wartość semncnt
zostanie zmniejszona o 1, natomiast funkcja systemowa zgłosi
błąd, przypisując zmiennej errno wartość EINTR.
Jeśli operacja zostanie zakończona pomyślnie, to wartości sempid
każdego z semaforów wyszczególnionych w tablicy wskazywanej przez sops
przypisany zostanie identyfikator procesu (PID), który wywołał semop.
Ponadto, polu sem_otime przypisany zostanie aktualny czas. Funkcja
semtimedop zachowuje się tak samo jak funkcja semop, poza tym że w tych
przypadkach gdy proces wywołujący by spał, czas trwania spania jest
ograniczony przez czas określony w strukturze timespec, do której adres
jest przekazywany w parametrze timeout. Jeśli osiągnięto określony
limit czasu, to wywołanie systemowe zwraca błąd, ustawiając errno na
EAGAIN (i żadna z operacji w sops nie jest wykonywana). Jeżeli
parametr timeout jest NULL, to semtimedop zachowuje się dokładnie tak
samo jak semop.
WARTOŚĆ ZWRACANA
Jeśli operacja zakończy się pomyślnie, wówczas funkcja zwróci 0, a w
przeciwnym wypadku zwróci -1, przypisując zmiennej errno kod
określający rodzaj błędu.
BŁĘDY
Po niepomyślnym zakończeniu, zmienna errno przyjmie jedną z
następujących wartości:
E2BIG Wartość nsops przekracza SEMOPM, maksymalną liczbę operacji
wykonywanych w jednym wywołaniu.
EACCES Proces nie ma uprawnień potrzebnych do wykonania jednej z
podanych operacji.
EAGAIN Operacja opatrzona znacznikiem IPC_NOWAIT w sem_flg nie może być
natychmiast wykonana lub upłynął limit czasu określony w
parametrze timeout.
EFAULT Adres wskazywany przez sops jest niedostępny.
EFBIG Numer semafora sem_num, do którego odnosi się jedna z operacji,
jest mniejszy od 0 albo większy lub równy liczbie semaforów w
zestawie.
EIDRM Zestaw został usunięty z systemu.
EINTR Podczas oczekiwania na wykonanie operacji proces przechwycił
sygnał.
EINVAL Zestaw semaforów nie istnieje lub wartość semid jest mniejsza od
0 lub wartość nsops nie jest liczbą dodatnią.
ENOMEM Brak pamięci na zapamiętanie zmian wywołanych przez operację
(znacznik SEM_UNDO w sem_flg).
ERANGE Dla pewnej operacji wartość sem_op+semval przekroczyła SEMVMX,
zależną od implementacji maksymalną wartość semval.
UWAGI
Struktury sem_undo nie są dziedziczone poprzez wywołania funkcji
systemowej fork(2), ale są dziedziczone poprzez wywołania funkcji
systemowej execve(2).
semop nie jest nigdy automatycznie uruchamiana ponownie po jej
przerwaniu przez funkcję obsługi sygnału, niezależnie od ustawień
znacznika SA_RESTART podczas tworzenia funkcji obsługi sygnału.
semadj jest przypisaną procesowi liczbą całkowitą, która stanowi po
prostu (ujemny) licznik wszystkich operacji na semaforach wykonanych z
podaniem znacznika SEM_UNDO. Podczas bezpośredniego nadawania wartości
semaforowi za pomocą poleceń SETVAL lub SETALL dla semctl(2),
odpowiednie wartości semadj dla wszystkich procesów są zerowane.
Wartości semval, sempid, semzcnt i semnct dla semafora można odczytać
za pomocą odpowiednich wywołań semctl(2).
Wywołania semop dotyczą następujące ograniczenia zasobów:
SEMOPM Maksymalna liczba operacji, które mogą być wykonane w jednym
wywołaniu semop: (32).
SEMVMX Maksymalna dozwolona wartość semval: zależy od implementacji
(32767).
Implementacja w systemie Linux nie nakłada wewnętrznych ograniczeń na
maksymalną zmianę wartości semafora podczas zakończenia procesu
(SEMAEM), na ogólnosystemową liczbę struktur przechowujących informacje
o zmianach stanu semaforów (SEMMNU), ani na maksymalną dla procesu
liczbę struktur przechowujących informacje o zmianach stanu semaforów.
USTERKI
Gdy proces kończy działanie, zestaw skojarzonych z nim struktur semadj
jest wykorzystywany do cofnięcia efektów wszystkich operacji na
semaforach, które ten proces wykonał z ustawionym znacznikiem SEM_UNDO.
Wprowadza to trudność: jeżeli jedna (lub więcej) spośród tych zmian
semaforów spowodowałby próbę zmniejszenia wartości semafora poniżej
zera, to co implementacja powinna uczynić? Jednym z możliwych podejść
do tego zadadnienia mogło by być zablokowanie do chwili, gdy
przeprowadzenie wszystkich zmian semaforów będzie możliwe. Jest to
jednakże niepożądane, gdyż spowodowałoby wymuszenie zablokowania
zakończenia procesu na dowolnie długi okres. Inną możliwością jest
zignorowanie wszystkich takich zmian semaforów (nieco analogiczne do
niepomyślnego zakończenia, gdy dla operacji na semaforze podany jest
znacznik IPC_NOWAIT). Linux przyjął trzecie rozwiązanie: zmniejszenie
wartości semafora na tyle, na ile jest to możliwe (tzn. do zera) i
umożliwienie natychmiastowej kontynuacji kończenia działania procesu.
ZGODNE Z
SVr4, SCID. SVr4 dokumentuje dodatkowe kody błędów: EINVAL, EFBIG i
ENOSPC.
ZOBACZ TAKŻE
ipc(5), semctl(2), semget(2), sigaction(2)