Provided by:
manpages-pl-dev_20051117-1_all 
NAZWA
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchroniczne
zwielokratnianie we/wy
SKŁADNIA
/* Zgodnie z POSIX 1003.1-2001 */
#include <sys/select.h>
/* Zgodnie z wcześniejszymi standardami */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set
*exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
OPIS
Funkcje select i pselect oczekują na zmianę statusu pewnej liczby
deskryptorów plików.
Ich funkcjonalność jest identyczna, jeśli pominąć trzy różnice:
(i) Funkcja select używa czasu parametru timeout, który jest typu
struct timeval (z sekundami i mikrosekundami), podczas gdy
pselect używa typu struct timespec (z sekundami i
nanosekundami).
(ii) Funkcja select może aktualizować parametr timeout, aby wskazać
jak dużo czasu minęło. Funkcja pselect nie zmienia tego
parametru.
(iii) Funkcja select nie posiada parametru sigmask i zachowuje się jak
pselect wywołane z NULL sigmask.
Podglądane są trzy niezależne zestawy deskryptorów. Te, które są
wymienione w readfds będą obserwowane w celu dowiedzenia się, czy nie
ma tam jakichś znaków dostępnych do czytania (dokładniej, aby
dowiedzieć się, czy read nie spowoduje zablokowania, desktyptor pliku
jest również przygotowany na koniec pliku). Deskryptory wymienione w
writefds będą obserwowane w celu dowiedzenia się, czy zapis nie
spowoduje blokady, a deskryptory wymienione w exceptfds będą
obserwowane w celu dowiedzenia się, czy nie ma na nich wyjątku. Przy
wyjściu, zbiory te są modyfikowane, wskazując, które z deskryptorów
zmieniły status.
Do obsługi tych zbiorów udostępnone są cztery makra: FD_ZERO czyści
zbiór. FD_SET i FD_CLR dodają, lub usuwają ze zbioru podany
deskryptor. FD_ISSET sprawdza, czy deskryptor jest częścią zbioru.
Jest to przydatne po zakończeniu select.
n jest nawyższym numerem deskryptora z wszystkich trzech zbiorów plus
1.
timeout jest górną granicą czasu, który upynie przed zakończeniem
działania funkcji select. Gdy przyjmie wartość zero, select zakończy
pracę natychmiast. (Jest to przydatne w uwspólnianiu.) Jeśli timeout
jest równe NULL (brak czasu przeterminowania), select może blokować w
nieskończoność.
sigmask jest wskaźnikiem do ksli sygnałów (zobacz sigprocmask(2)).
Jeśli nie jest równe NULL, to pselect najpierw zastępuje bieżącą maskę
sygnałów maską wskazywaną przez sigmask, a następnie wywołuje funkcję
`select' i ponownie odtwarza originalną maskę sygnałów.
Idea pselect polega na tym, że gdy chce się oczekiwać na zdarzenie
będące sygnałem lub czymś na deskryptorze pliku, potrzebny jest atomowy
test zapobiegający sytuacjom wyścigu. (Przypuśćmy, że procedura obsługi
sygnału ustawia globalny znacznik i kończy działanie. Wówczas, test
tego znacznika globalnego, po którym następuje wywołanie select() może
wisieć w nieskończoność, gdyby sygnał przybył natychmiast po teście,
ale przed wywołaniem. Inaczej mówiąc, pselect zezwala na, najpierw,
zablokowanie sygnałów, następnie obsłużenie dostarczonych sygnałów, aby
wreszcie wywołać pselect() z pożądanym sigmask, unikając wyścigu.)
Ponieważ obecnie Linux nie posiada funkcji systemowej pselect(),
aktualna procedura w glibc2 wciąż zawiera ryzyko takiego wyścigu.
Przeterminowanie
Struktury czasu, których to dotyczy, są zdefiniowane w <sys/time.h> i
wyglądają następująco
struct timeval {
long tv_sec; /* sekundy */
long tv_usec; /* mikrosekundy */
};
i
struct timespec {
long tv_sec; /* sekundy */
long tv_nsec; /* nanosekundy */
};
(Jednakże odnośnie wersji POSIX 1003.1-2001 zobacz poniżej.)
Niektóre programy wywołują select z wszystkimi trzema zbiorami pustymi,
z n równym zeru i niezerowym timeout. Jest to całkiem przenośny sposób
pauzowania z dokładnością subsekundową.
Pod Linuksem funkcja select modyfikuje timeout, aby odzwierciedlić
ilość nieprzespanego czasu; większość innych implementacji tego nie
robi. Powoduje to problemy, zarówno gdy kod linuksowy odczytujący
timeout zostanie przeniesiony na inne systemy operacyjne, jak i gdy kod
przeniesiony pod Linuksa z innych systemów używa ponownie struct
timeval dla wielu selectów w pętli, bez reinicjalizacji. Należy
traktować timeout jako niezdefiniowany po zakończeniu select.
WARTOŚĆ ZWRACANA
Po pomyślnym zakończeniu, select i pselect zwracają liczbę deskryptorów
w zbiorach deskryptorów. Może ona być zerowa, jeśli nastąpi
przeterminowanie nim coś ciekawego się zdarzy. Po błędzie, zwracane
jest -1 i odpowiednio ustawiane errno; zbiory deskryptorów i timeout
stają się niezdefiniowane, więc nie należy polegać na ich zawartości.
BŁĘDY
EBADF W jednym ze zbiorów podano nieprawidłowy deskryptor pliku.
EINTR Przechwycono nieblokowany sygnał.
EINVAL n jest ujemne lub wartość timeout jest nieprawidłowa.
ENOMEM select nie był w stanie przydzielić pamięci dla wewnętrznych
tablic.
PRZYKŁAD
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Obserwacja stdin (fd 0) i sprawdzanie kiedy ma wejście. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Czekanie nie dłużej niż sekund. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Nie należy już polegać na wartości tv! */
if (retval)
printf("Dane są już dostępne.\n");
/* FD_ISSET(0, &rfds) będzie prawdziwy. */
else
printf("Brak danych w ciągu 5 sekund.\n");
exit(0);
}
ZGODNE Z
4.4BSD (funkcja select pojawiła się pierwotnie w 4.2BSD). W ogólności
przenośne do/z systemów nie-BSD wspierających sklonowaną warstwę gniazd
BSD (włączając warianty Systemu V). Jednakże, należy zauważyć, że
warianty Systemu V zasadniczo ustawiają zmienną timeout przed
zakończeniem, ale wariant BSD tego nie robi.
Funkcja pselect jest zdefiniowana w IEEE Std 1003.1g-2000 (POSIX.1g)
oraz częściowo w POSIX 1003.1-2001. Można ją znaleźć w glibc2.1 i
późniejszych. Glibc2.0 zawiera funkcję o tej samej nazwie, która
jednakże, nie posiada parametru sigmask.
UWAGI
fd_set jest buforem o stałym rozmiarze. Wykonanie FD_CLR lub FD_SET z
ujemną wartością fd albo z wartością większą lub równą FD_SETSIZE
spowoduje zachowanie niezdefiniowane. Ponadto POSIX wybaga, by fd był
prawidłowym deskryptorem pliku.
Odnośnie używanych typów, klasyczna sytuacja polega na tym, że oba pola
struktury struct timeval są typu long (jak pokazano powyżej), a sama
struktura jest zdefiniowana w <sys/time.h>. W POSIX 1003.1-2001
sytuacja jest następująca
struct timeval {
time_t tv_sec; /* sekundy */
suseconds_t tv_usec; /* mikrosekundy */
};
przy czym struktura jest zdefiniowana w <sys/select.h> a typy time_t i
suseconds_t zdefiniowano w <sys/types.h>.
Odnośnie prototypów, klasyczna sytuacja polega na tym, że dla select
należy włączyć <time.h>. Sytuacja z POSIX 1003.1-2001 polega na tym,
że dla select i pselect należy włączyć <sys/select.h>. libc4 i libc5
nie zawierają pliku nagłówkowego <sys/select.h>; w glibc 2.0 i
późniejszymi ten plik nagłówkowy istnieje. W glibc 2.0 udostępnia on
bezwarunkowo błędny prototyp dla pselect. W glibc 2.1-2.2.1 udostępnia
on pselect, gdy zdefiniowane jest _GNU_SOURCE. W glibc 2.2.2-2.2.4
udostępnia go natomiast, gdy zdefiniowane jest _XOPEN_SOURCE i ma
wartość 600 lub większą. Niewątpliwie, począwszy od POSIX 1003.1-2001
plik ten powinien udostępniać prototyp standardowo.
ZOBACZ TAKŻE
Samouczek z dyskusją i przykładami znajduje się w select_tut(2).
Rzeczy w nieokreślony sposób powiązane z tym można znaleźć w accept(2),
connect(2), poll(2), read(2), recv(2), send(2), sigprocmask(2),
write(2)