Provided by:
manpages-pl-dev_20060617-3_all 
NAZWA
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchroniczne
zwielokratnianie we/wy
SK/LADNIA
/* Zgodnie z POSIX 1003.1-2001 */
#include <sys/select.h>
/* Zgodnie z wczeniejszymi standardami */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
#define _XOPEN_SOURCE 600
#include <sys/select.h>
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
OPIS
select() i pselect() umoliwiaj programowi monitorowanie wielu
deskryptorow plikow i oczekiwanie a jeden lub wicej deskryptorow bdzie
"gotowy" na wykonanie pewnej klasy operacji wejcia/wyjcia (np. moliwy
odczyt). Deskryptor pliku jest uwaany za gotowy, jeeli moliwe jest
wykonanie odpowiadajcej operacji (np. read(2)) bez blokowania.
Funkcjonalno funkcji select() i pselect() jest identyczna, jeli pomin
trzy ronice:
(i) Funkcja select() uywa czasu parametru timeout, ktory jest typu
struct timeval (z sekundami i mikrosekundami), podczas gdy
pselect() uywa typu struct timespec (z sekundami i
nanosekundami).
(ii) Funkcja select() moe aktualizowa parametr timeout, aby wskaza,
jak duo czasu minlo. Funkcja pselect() nie zmienia tego
parametru.
(iii) Funkcja select() nie przykmuje parametru sigmask i zachowuje si,
jak pselect() wywolane z NULL sigmask.
Podgldane s trzy niezalene zestawy deskryptorow. Te, ktore s wymienione
w readfds bd obserwowane w celu dowiedzenia si, czy nie ma tam jakich
znakow dostpnych do czytania (dokladniej, aby dowiedzie si, czy read
nie spowoduje zablokowania, deskryptor pliku jest rownie przygotowany
na koniec pliku). Deskryptory wymienione w writefds bd obserwowane w
celu dowiedzenia si, czy zapis nie spowoduje blokady, a deskryptory
wymienione w exceptfds bd obserwowane w celu dowiedzenia si, czy nie ma
na nich wyjtku. Przy wyjciu, zbiory te s modyfikowane, wskazujc, ktore
z deskryptorow zmienily status. Kady z tych trzech zbiorow deskryptorow
plikow moe by przekazany jako NULL, jeeli dla adnego deskryptora pliku
na ma potrzeby obserwowania odpowiedniej klasy zdarze.
Do obslugi tych zbiorow udostpnione s cztery makra: FD_ZERO() czyci
zbior. FD_SET() i FD_CLR() dodaj lub usuwaj ze zbioru podany
deskryptor. FD_ISSET() sprawdza, czy deskryptor jest czci zbioru. Jest
to przydatne po zakoczeniu select().
nfds jest najwyszym numerem deskryptora z wszystkich trzech zbiorow
plus 1.
timeout jest gorn granic czasu, ktory uplynie przed zakoczeniem
dzialania funkcji select(). Gdy przyjmie warto zero, select() zakoczy
prac natychmiast. (Jest to przydatne w uwspolnianiu). Jeli timeout jest
rowne NULL (brak czasu przeterminowania), select() moe blokowa w
nieskoczono.
sigmask jest wskanikiem do maski sygnalow (zobacz sigprocmask(2)). Jeli
nie jest rowne NULL, to pselect() najpierw zastpuje biec mask sygnalow
mask wskazywan przez sigmask, a nastpnie wywoluje funkcj `select' i
ponownie odtwarza oryginaln mask sygnalow.
Poza ronic w precyzji argumentu timeout, nastpujce wywolanie pselect():
ready = pselect(nfds, &readfds, &writefds, &exceptfds,
timeout, &sigmask);
jest odpowiednikiem niepodzielnego wykonania nastpujcych funkcji:
sigset_t origmask;
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
Idea pselect() polega na tym, e gdy chce si oczekiwa na zdarzenie bdce
sygnalem lub czym na deskryptorze pliku, potrzebny jest atomowy test
zapobiegajcy sytuacjom wycigu. (Przypumy, e procedura obslugi sygnalu
ustawia globalny znacznik i koczy dzialanie. Wowczas, test tego
znacznika globalnego, po ktorym nastpuje wywolanie select() moe wisie w
nieskoczono, gdyby sygnal przybyl natychmiast po tecie, ale przed
wywolaniem. Inaczej mowic, pselect zezwala na, najpierw, zablokowanie
sygnalow, nastpnie obsluenie dostarczonych sygnalow, aby wreszcie
wywola pselect() z podanym sigmask, unikajc wycigu).
Przeterminowanie
Struktury czasu, ktorych to dotyczy, s zdefiniowane w <sys/time.h> i
wygldaj nastpujco
struct timeval {
long tv_sec; /* sekundy */
long tv_usec; /* mikrosekundy */
};
i
struct timespec {
long tv_sec; /* sekundy */
long tv_nsec; /* nanosekundy */
};
(Jednake odnonie wersji POSIX 1003.1-2001 zobacz poniej).
Niektore programy wywoluj select() z wszystkimi trzema zbiorami
pustymi, z n rownym zeru i niezerowym timeout. Jest to calkiem przenony
sposob pauzowania z dokladnoci subsekundow.
Pod Linuksem funkcja select() modyfikuje timeout, aby odzwierciedli ilo
nieprzespanego czasu; wikszo innych implementacji tego nie robi
(POSIX.1-2001 dopuszcza oba te zachowania). Powoduje to problemy,
zarowno gdy kod linuksowy odczytujcy timeout zostanie przeniesiony na
inne systemy operacyjne, jak i gdy kod przeniesiony pod Linuksa z
innych systemow uywa ponownie struct timeval dla wielu select()ow w
ptli, bez powtornej inicjacji. Naley traktowa timeout jako
niezdefiniowany po zakoczeniu select().
WARTO ZWRACANA
Po pomylnym zakoczeniu, select() i pselect() zwracaj liczb deskryptorow
w zbiorach deskryptorow (to jest calkowit liczb bitow ustawion w
readfds, writefds, exceptfds). Moe ona by zerowa, jeli nastpi
przeterminowanie, nim co ciekawego si zdarzy. Po bldzie, zwracane jest
-1 i odpowiednio ustawiane errno; zbiory deskryptorow i timeout staj si
niezdefiniowane, wic nie naley polega na ich zawartoci.
B/LDY
EBADF W jednym ze zbiorow przekazano niepoprawny deskryptor pliku (By
moe deskryptor ten zostal ju zamknity lub wystpil na nim inny
bld).
EINTR Przechwycono sygnal.
EINVAL nfds jest ujemne lub warto timeout jest nieprawidlowa.
ENOMEM nie mona bylo przydzieli pamici dla wewntrznych tablic.
PRZYK/LAD
#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 wejcie. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Czekanie nie dluej ni 5 sekund. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Nie naley ju polega na wartoci tv! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Dane s ju dostpne.\n");
/* FD_ISSET(0, &rfds) bdzie prawdziwy. */
else
printf("Brak danych w cigu 5 sekund.\n");
return 0;
}
ZGODNE Z
BSD 4.4 (funkcja select() pojawila si pierwotnie w BSD 4.2). W ogolnoci
przenone do/z systemow nie-BSD wspierajcych sklonowan warstw gniazd BSD
(wlczajc warianty Systemu V). Jednake, naley zauway, e warianty Systemu
V zasadniczo ustawiaj zmienn timeout przed zakoczeniem, ale wariant BSD
tego nie robi.
pselect() jest zdefiniowany w IEEE Std 1003.1g-2000 (POSIX.1g) i w
POSIX 1003.1-2001.
UWAGI
fd_set jest buforem o stalym rozmiarze. Wykonanie FD_CLR() lub FD_SET()
z ujemn wartoci fd albo z wartoci wiksz lub rown FD_SETSIZE spowoduje
zachowanie niezdefiniowane. Ponadto POSIX wymaga, by fd byl prawidlowym
deskryptorem pliku.
Odnonie uywanych typow, klasyczna sytuacja polega na tym, e oba pola
struktury timeval s typu long (jak pokazano powyej), a sama struktura
jest zdefiniowana w <sys/time.h>. W POSIX 1003.1-2001 sytuacja jest
nastpujca
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>.
Odnonie do prototypow, klasyczna sytuacja polega na tym, e dla select()
naley wlczy <time.h>. Sytuacja z POSIX 1003.1-2001 polega na tym, e dla
select() i pselect() naley wlczy <sys/select.h>. libc4 i libc5 nie
zawieraj pliku naglowkowego <sys/select.h>; w glibc 2.0 i poniejszymi
ten plik naglowkowy istnieje. W glibc 2.0 udostpnia on bezwarunkowo
bldny prototyp dla pselect(). W glibc 2.1-2.2.1 udostpnia on pselect(),
jeeli zdefiniowane jest _GNU_SOURCE. W glibc 2.2.2-2.2.4 udostpnia go
natomiast, gdy zdefiniowane jest _XOPEN_SOURCE i ma warto 600 lub
wiksz. Niewtpliwie, poczwszy od POSIX 1003.1-2001 plik ten powinien
udostpnia prototyp standardowo.
WERSJE
pselect() zostal dodany do jadra Linuksa 2.6.16.
Wczeniej pselect() byl emulowany w glibc (patrz rownie BLDY
IMPLEMENTACJI).
UWAGI LINUKSOWE
Wywolanie systemowa pselect() pod Linuksem modyfikuje argument timeout.
Jednake funkcja glibc ukrywa to zachowanie przez uycie dla argumentu
timeout lokalnej zmiennej, ktora jest przekazywana do wywolania
systemowego. Dlatego pselect() z glibc nie zmienia argumentu timeout,
co jest zachowaniem wymaganym przez POSIX.1-2001.
B/LDY IMPLEMENTACJI
Glibc 2.0 dostarczala wersj pselect(), ktora nie przyjmowala argumentu
sigmask.
Od wersji 2.1 glibc dostarczal emulacj pselect(), ktora byla
zaimplementowana przy uyciu sigprocmask(2) i select(). Implementacja ta
pozostaje podatna na wiele bldow wycigow (race conditions), ktorych
uniknicie stanowilo ide funkcji pselect(). W systemach, ktore nie maj
pselect() niezawodne (i bardziej przenone) przechwytywanie sygnalow
mona osign, uywajc triku potoku do siebie (gdzie procedura obslugi
sygnalu zapisuje bajt do potoku, ktorego drugi koniec jest monitorowany
przez select() w glownym programie).
Pod Linuksem select() moe raportowa deskryptory plikow gniazd jako
"dostpne do czytania", podczas gdy kolejne czytania zostan zablokowane.
Moe to si zdarzy na przyklad wtedy, gdy dane nadeszly, ale podczas
sprawdzania okazalo si, e maj zl sum kontroln i zostaly odrzucone. Mog
wystpi take inne sytuacje, w ktorych deskryptor pliku jest bldnie
raportowany jako gotowy. Dlatego uywanie O_NONBLOCK na gniazdach, ktore
nie powinny si blokowa moe by bezpieczniejsze.
ZOBACZ TAKE
Samouczek z dyskusj i przykladami znajduje si w select_tut(2).
Rzeczy w nieokrelony sposob powizane z tym mona znale w accept(2),
connect(2), poll(2), read(2), recv(2), send(2), sigprocmask(2),
write(2), epoll(7), feature_test_macros(7)
INFORMACJE O T/LUMACZENIU
Powysze tlumaczenie pochodzi z nieistniejcego ju Projektu Tlumaczenia
Manuali i moe nie by aktualne. W razie zauwaenia ronic midzy powyszym
opisem a rzeczywistym zachowaniem opisywanego programu lub funkcji,
prosimy o zapoznanie si z oryginaln (angielsk) wersj strony podrcznika.