Rechercher une page de manuel

Chercher une autre page de manuel:

FD_SET

Autres langues

Langue: pl

Version: 2006\-03\-11 (ubuntu - 01/11/07)

Autres sections - même nom

Section: 2 (Appels système)

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 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() umo¿liwiaj± programowi monitorowanie wielu deskryptorów plików i oczekiwanie a¿ jeden lub wiêcej deskryptorów bêdzie "gotowy" na wykonanie pewnej klasy operacji wej¶cia/wyj¶cia (np. mo¿liwy odczyt). Deskryptor pliku jest uwa¿any za gotowy, je¿eli mo¿liwe jest wykonanie odpowiadaj±cej operacji (np. read(2)) bez blokowania.

Funkcjonalno¶æ funkcji select() i pselect() 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 przykmuje 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, deskryptor 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. Ka¿dy z tych trzech zbiorów deskryptorów plików mo¿e byæ przekazany jako NULL, je¿eli dla ¿adnego deskryptora pliku na ma potrzeby obserwowania odpowiedniej klasy zdarzeñ.

Do obs³ugi tych zbiorów udostêpnione 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().

nfds jest najwy¿szym numerem deskryptora z wszystkich trzech zbiorów plus 1.

timeout jest górn± granic± czasu, który up³ynie 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 maski 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 oryginaln± maskê sygna³ów.

Poza ró¿nic± w precyzji argumentu timeout, nastêpuj±ce wywo³anie pselect():

 
     ready = pselect(nfds, &readfds, &writefds, &exceptfds, 
                     timeout, &sigmask);
 
 
jest odpowiednikiem niepodzielnego wykonania nastêpuj±cych 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 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).

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 (POSIX.1-2001 dopuszcza oba te zachowania). 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 powtórnej inicjacji. 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 (to jest ca³kowitê liczbê bitów ustawion± w readfds, writefds, exceptfds). 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 przekazano niepoprawny deskryptor pliku (Byæ mo¿e deskryptor ten zosta³ ju¿ zamkniêty lub wyst±pi³ na nim inny b³±d).
EINTR
Przechwycono sygna³.
EINVAL
nfds jest ujemne lub warto¶æ timeout jest nieprawid³owa.
ENOMEM
nie mo¿na by³o 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¿ 5 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 == -1)
         perror("select()");
     else 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");
 
     return 0;
 }
 

ZGODNE Z

BSD 4.4 (funkcja select() pojawi³a siê pierwotnie w BSD 4.2). 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.

pselect() jest zdefiniowany w IEEE Std 1003.1g-2000 (POSIX.1g) i w POSIX 1003.1-2001.

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 wymaga, by fd by³ prawid³owym deskryptorem pliku.

Odno¶nie u¿ywanych typów, klasyczna sytuacja polega na tym, ¿e oba pola struktury 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 do 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(), je¿eli 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.

WERSJE

pselect() zosta³ dodany do jadra Linuksa 2.6.16.

Wcze¶niej pselect() by³ emulowany w glibc (patrz równie¿ B£ÊDY IMPLEMENTACJI).

UWAGI LINUKSOWE

Wywo³anie systemowa pselect() pod Linuksem modyfikuje argument timeout. Jednak¿e funkcja glibc ukrywa to zachowanie przez u¿ycie dla argumentu timeout lokalnej zmiennej, która jest przekazywana do wywo³ania systemowego. Dlatego pselect() z glibc nie zmienia argumentu timeout, co jest zachowaniem wymaganym przez POSIX.1-2001.

B£ÊDY IMPLEMENTACJI

Glibc 2.0 dostarcza³a wersjê pselect(), która nie przyjmowa³a argumentu sigmask.

Od wersji 2.1 glibc dostarcza³ emulacjê pselect(), która by³a zaimplementowana przy u¿yciu sigprocmask(2) i select(). Implementacja ta pozostaje podatna na wiele b³êdów wy¶cigów (race conditions), których unikniêcie stanowi³o ideê funkcji pselect(). W systemach, które nie maj± pselect() niezawodne (i bardziej przeno¶ne) przechwytywanie sygna³ów mo¿na osi±gn±æ, u¿ywaj±c triku potoku do siebie (gdzie procedura obs³ugi sygna³u zapisuje bajt do potoku, którego drugi koniec jest monitorowany przez select() w g³ównym programie).

Pod Linuksem select() mo¿e raportowaæ deskryptory plików gniazd jako "dostêpne do czytania", podczas gdy kolejne czytania zostan± zablokowane. Mo¿e to siê zdarzyæ na przyk³ad wtedy, gdy dane nadesz³y, ale podczas sprawdzania okaza³o siê, ¿e maj± z³± sumê kontroln± i zosta³y odrzucone. Mog± wyst±piæ tak¿e inne sytuacje, w których deskryptor pliku jest b³êdnie raportowany jako gotowy. Dlatego u¿ywanie O_NONBLOCK na gniazdach, które nie powinny siê blokowaæ mo¿e byæ bezpieczniejsze.

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), epoll(7), feature_test_macros(7)

La science (comme la chimie) est de nos jours internationale et
mondiale; les communications, les informations, les échanges de
biens ainsi que la pollution franchissent les frontières et
inondent notre globe.
Ceci implique une solidarité mondiale croissante ou des choix au
niveau mondial. En sommes-nous conscients ?
-+- Joachim Charles Hitzke -+-