select

Autres langues

Langue: pl

Autres versions - même langue

Version: 2001-02-09 (openSuse - 09/10/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 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)