select

SELECT(2)               PodrÄcznik programisty Linuksa               SELECT(2)



NAZWA
       select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchroniczne
       zwielokrotnianie wejÅcie/wyjÅcie

SKÅADNIA
       /* Zgodnie z POSIX.1-2001, POSIX.1-2008 */
       #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);

       #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);

   Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

       pselect(): _POSIX_C_SOURCE >= 200112L

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 wejÅcia/wyjÅcia (np.
       read(2) bez blokowania lub odpowiednio maÅe write(2)).

       select() może monitorowaÄ wyÅÄcznie numery deskryptorów plików
       mniejsze niż FD_SETSIZE; poll(2) nie posiada tego ograniczenia. Zob.
       BÅÄDY.

       FunkcjonalnoÅÄ funkcji select() i pselect() jest identyczna, jeÅli
       pominÄÄ trzy różnice:

       (i)    Funkcja select() używa dla parametru timeout 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 przyjmuje parametru sigmask i zachowuje
              siÄ, jak pselect() wywoÅane z NULL-em przekazanym w 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 jest dostÄpna
       przestrzeÅ do zapisu (choÄ duże zapisy wciÄż mogÄ byÄ blokowane), 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.

       Argument timeout okreÅla interwaÅ, który powinien blokowaÄ select(),
       czekajÄc na gotowoÅÄ deskryptora plików. WywoÅanie bÄdzie skutkowaÅo
       blokadÄ do momentu aż:

       *  deskryptor pliku stanie siÄ dostÄpny

       *  lub wywoÅanie zostanie przerwane procedurÄ obsÅugi sygnaÅu

       *  albo wywoÅanie przeterminuje siÄ

       ProszÄ zauważyÄ, że interwaÅ zostanie zaokrÄglony w górÄ do
       dokÅadnoÅci zegara, a wystÄpowanie opóźnienia planisty jÄdra oznacza,
       że ten interwaÅ może byÄ nieznacznie przekroczony. JeÅli oba pola
       struktury timeval majÄ 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", a po jej zakoÅczeniu 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;

           pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
           ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
           pthread_sigmask(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 zobacz poniżej uwagi dotyczÄce POSIX.1).

       Niektóre programy wywoÅujÄ select() z wszystkimi trzema zbiorami
       pustymi, z nfds 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 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 struktury timeval dla wielu wywoÅaÅ
       select() w pÄtli, bez powtórnej inicjacji. Prosimy rozważyÄ
       traktowanie wartoÅci timeout jako niezdefiniowanej po zakoÅczeniu
       funkcji 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 aby wskazaÄ bÅÄd; zbiory
       deskryptorów nie sÄ modyfikowane, a timeout staje siÄ niezdefiniowane.

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Å, patrz signal(7).

       EINVAL nfds jest ujemne lub przekracza limit zasobów RLIMIT_NOFILE
              (zob. getrlimit(2)).

       EINVAL WartoÅÄ timeout jest nieprawidÅowa.

       ENOMEM Nie można byÅo przydzieliÄ pamiÄci dla wewnÄtrznych tablic.

WERSJE
       pselect() zostaÅ dodany w wersji 2.6.16 jÄdra Linuksa. WczeÅniej
       pselect() byÅ emulowany w glibc (patrz również BÅÄDY IMPLEMENTACJI).

ZGODNE Z
       select() jest zgodny z POSIX.1-2001, POSIX.1-2008 i BSD 4.4 (funkcja
       select() pojawiÅa siÄ pierwotnie w BSD 4.2). W ogólnoÅci jest
       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 POSIX.1g, w POSIX.1-2001 i w
       POSIX.1-2008.

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.

       Na niektórych innych systemach Uniksowych select() może zwróciÄ bÅÄd
       EAGAIN jeÅli systemowi nie uda siÄ przydzieliÄ wewnÄtrzjÄdrowych
       zasobów, zamiast ENOMEM, tak jak robi to Linux. POSIX przewiduje ten
       bÅÄd dla poll(2), lecz nie dla select(). PrzenoÅne programy mogÄ chcieÄ
       sprawdzaÄ EAGAIN w pÄtli, tak jak dla EINTR.

       JeÅli chodzi o używane typy, 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.1 wyglÄda to
       nastÄpujÄco:

           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>.

       JeÅli chodzi o prototypy opisywanych funkcji, to klasyczna sytuacja
       polega na tym, że dla select() należy wÅÄczyÄ <time.h>, natomiast
       sytuacja z POSIX.1 polega na tym, że dla select() i pselect() należy
       wÅÄczyÄ <sys/select.h>.

       W glibc 2.0 <sys/select.h> udostÄpnia bezwarunkowo bÅÄdny prototyp dla
       pselect(). W glibc 2.1 aż do 2.2.1 udostÄpnia on pselect(), jeżeli
       zdefiniowane jest _GNU_SOURCE. Od glibc 2.2.2 wymagania sÄ takie, jak
       pokazano powyżej w rozdziale SKÅADNIA.

   Aplikacje wielowÄtkowe
       JeÅli deskryptor plików monitorowany przez select() zostanie zamkniÄty
       w innym wÄtku, to rezultat jest nieokreÅlony. Na niektórych systemach
       uniksowych select() odblokuje go i powróci wskazujÄc, że dany
       deskryptor plików jest gotowy (kolejne operacje wyjÅcia/wyjÅcia
       prawdopodobnie zakoÅczÄ siÄ bÅÄdem, chyba że otwarty zostanie inny
       deskryptor plików w czasie pomiÄdzy powrotem select() a wykonanie
       operacji wejÅcia/wyjÅcia. W systemie Linux (i czÄÅci innych) zamkniÄcie
       deskryptora pliku w innym wÄtku nie wpÅynie na select(). PodsumowujÄc,
       każda aplikacja polegajÄca na konkretnym zachowaniu w takim przypadku
       musi byÄ uznana za bÅÄdnÄ.

   Różnice biblioteki C/jÄdra
       JÄdro Linux pozwala deskryptorowi pliku ustawiÄ dowolny rozmiar, na
       podstawie dÅugoÅci zestawów do sprawdzenia z wartoÅci nfds. Jednak w
       implementacji glibc, typ fd_set ma staÅy rozmiar. Zob. też BÅÄDY.

       Interfejs pselect() opisany w niniejszym podrÄczniku jest
       zaimplementowany w glibc. StojÄce za nim linuksowe wywoÅanie systemowe
       nazywa siÄ pselect6(). Cechuje go nieco inne zachowanie od opisywanej
       funkcji opakowujÄcej glibc.

       WywoÅanie systemowe pselect6() 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.

       Ostatnim argumentem wywoÅania systemowego pselect6() nie jest wskaźnik
       sigset_t * lecz struktura postaci:

           struct {
               const sigset_t *ss;     /* Pointer to signal set */
               size_t          ss_len; /* Size (in bytes) of object pointed
                                          to by 'ss' */
           };

       Pozwala to wywoÅaniu systemowemu pobraÄ oba wskaźniki do zestawu
       sygnaÅowego wraz z rozmiarem, biorÄc pod uwagÄ, że wiÄkszoÅÄ
       architektur obsÅuguje maksymalnie 6 argumentów do wywoÅania
       systemowego.

BÅÄDY IMPLEMENTACJI
       POSIX pozwala implementacji zdefiniowaÄ górny limit zakresu
       deskryptorów plików, które można podaÄ w zestawie deskryptora
       pliku, rozgÅaszany staÅÄ FD_SETSIZE. JÄdro Linux nie wymusza staÅego
       limitu, lecz implementacja glibc czyni fd_set typem o staÅym rozmiarze,
       z FD_SETSIZE zdefiniowanym jako 1024 i makrami FD_*() dziaÅajÄcymi
       zgodnie z tym limitem. Aby monitorowaÄ deskryptory plików wiÄksze niż
       1023, należy w zamian użyÄ poll(2).

       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(). Nowsze wersje
       glibc używajÄ (wolnego od wyÅcigów) wywoÅania systemowego, jeÅli
       tylko jÄdro dostarcza takiego wywoÅania.

       W systemach, które nie majÄ pselect() niezawodne (i bardziej
       przenoÅne) przechwytywanie sygnaÅów można osiÄgnÄÄ, używajÄc
       sztuczki w postaci "potoku do siebie". W tej technice procedura obsÅugi
       sygnaÅu zapisuje bajt do potoku, którego drugi koniec jest
       monitorowany przez select() w gÅównym programie. Aby uniknÄÄ
       możliwego zablokowania przy pisaniu do potoku który może byÄ peÅny
       lub czytaniu z potoku który może byÄ pusty, przy czytaniu z i pisaniu
       do potoku używane jest nieblokujÄce wejÅcie/wyjÅcie.

       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.

       Pod Linuksem wywoÅanie select() zmienia wartoÅÄ timeout także wtedy,
       gdy zostanie przerwane przez procedurÄ obsÅugi sygnaÅu (tj. zostanie
       zwrócony bÅÄd EINTR). POSIX.1 nie pozwala na takie zachowanie.
       WywoÅanie systemowe pselect() pod Linuksem zachowuje siÄ tak samo, ale
       funkcja opakowujÄca biblioteki glibc ukrywa to zachowanie, kopiujÄc
       wartoÅÄ timeout do wewnÄtrznej lokalnej zmiennej i przekazujÄc tÄ
       zmiennÄ do wywoÅania systemowego.

PRZYKÅAD
       #include <stdio.h>
       #include <stdlib.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");

           exit(EXIT_SUCCESS);
       }

ZOBACZ TAKŻE
       accept(2), connect(2), poll(2), read(2), recv(2), restart_syscall(2),
       send(2), sigprocmask(2), write(2), epoll(7), time(7)

       Samouczek z dyskusjÄ i przykÅadami znajduje siÄ w select_tut(2).

O STRONIE
       Angielska wersja tej strony pochodzi z wydania 4.07 projektu Linux
       man-pages. Opis projektu, informacje dotyczÄce zgÅaszania bÅÄdów, oraz
       najnowszÄ wersjÄ oryginaÅu można znaleÅºÄ pod adresem
       https://www.kernel.org/doc/man-pages/.

TÅUMACZENIE
       Autorami polskiego tÅumaczenia niniejszej strony podrÄcznika man sÄ:
       Przemek Borys (PTM) <pborys@dione.ids.pl>, Robert Luberda
       <robert@debian.org> i MichaÅ KuÅach <michal.kulach@gmail.com>.

       Polskie tÅumaczenie jest czÄÅciÄ projektu manpages-pl; uwagi, pomoc,
       zgÅaszanie bÅÄdów na stronie http://sourceforge.net/projects/manpages-
       pl/. Jest zgodne z wersjÄ  4.07 oryginaÅu.



Linux                             2016-03-15                         SELECT(2)