Provided by: manpages-pl-dev_0.6-2_all bug

NAZWA

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

SKŁADNIA

       /* Zgodnie z POSIX.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);

       #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 || _XOPEN_SOURCE >= 600

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

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

       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-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  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 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 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 i w POSIX.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.

       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-2001 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 1003.1-2001 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 ABI biblioteki C/jądra
       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

       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-2001
       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),  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  3.71  projektu  Linux  man-pages.  Opis
       projektu,  informacje  dotyczące  zgłaszania błędów, oraz najnowszą wersję oryginału można
       znaleźć pod adresem http://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ą   3.71
       oryginału.