Provided by: manpages-pl-dev_0.7-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, 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.