Rechercher une page de manuel

Chercher une autre page de manuel:

FD_CLR

Autres langues

Langue: pl

Autres versions - même langue

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)

MultideskOS est un OS. Il ne gère pas (encore) le secteur boot, mais le
fera par la suite. Comme il a ses propres formats de fichier, et qu'il
gère tout, on considère que c'est un OS et non un Shell.
-- Jayce - Tanenbaum ? Qui c'est ça ? --