Provided by: manpages-pl-dev_4.23.1-1_all bug

NAZWA

       select,  pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO, fd_set - synchronicznie zwielokrotnia
       wejście/wyjście

BIBLIOTEKA

       Standardowa biblioteka C (libc, -lc)

SKŁADNIA

       #include <sys/select.h>

       typedef /* ... */ fd_set;

       int select(int nfds, fd_set *_Nullable restrict readfds,
                  fd_set *_Nullable restrict writefds,
                  fd_set *_Nullable restrict exceptfds,
                  struct timeval *_Nullable restrict 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);

       int pselect(int nfds, fd_set *_Nullable restrict readfds,
                  fd_set *_Nullable restrict writefds,
                  fd_set *_Nullable restrict exceptfds,
                  const struct timespec *_Nullable restrict timeout,
                  const sigset_t *_Nullable restrict sigmask);

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

       pselect():
           _POSIX_C_SOURCE >= 200112L

OPIS

       OSTRZEŻENIE: select() potrafi monitorować deskryptory plików  o  numerach  mniejszych  niż
       FD_SETSIZE  (1024)  —  limit  nierozsądnie niewielki dla wielu współczesnych aplikacji — i
       ograniczenie to nie zmieni się. Wszystkie współczesne aplikacje powinny w zamian korzystać
       z poll(2) lub epoll(7), które nie mają tego ograniczenia.

       select()  umożliwia  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)   lub
       odpowiednio małe write(2)) bez blokowania.

   fd_set
       Typ  struktury mogącej reprezentować zbiór deskryptorów pliku. Zgodnie z POSIX, maksymalną
       liczbą deskryptorów pliku w strukturze fd_set jest wartość makra FD_SETSIZE.

   Zbiory deskryptorów pliku
       Podstawowymi argumentami select() są trzy „zbiory” deskryptorów pliku (zadeklarowane  jako
       typ  fd_set),  pozwalające  wywołującemu  na  oczekiwanie na trzy klasy zdarzeń na zadanym
       zbiorze deskryptorów pliku. Każdy  argument  fd_set  można  podać  jako  NULL,  jeśli  dla
       odpowiadającej klasy zdarzeń nie mają być monitorowane deskryptory pliku.

       Proszę  zwrócić  szczególną  uwagę:  Po powrocie, każdy ze zbiorów deskryptorów pliku jest
       modyfikowany w miejscu, aby wskazać, które z deskryptorów pliku są aktualnie  „gotowe”.  Z
       tego  względu, jeśli select() jest używany w pętli, zbiory muszą być zainicjowane ponownie
       przed każdym wywołaniem.

       Zawartością zbiorów deskryptorów pliku można manipulować za pomocą następujących makr:

       FD_ZERO()
              Makro czyści (usuwa z niego wszystkie deskryptory pliku)  set.  Powinno  być  użyte
              jako pierwszy krok w inicjowaniu zbiorów deskryptorów pliku.

       FD_SET()
              Makro  dodaje  deskryptor  pliku fd do zbioru set. Dodanie deskryptora pliku, który
              jest już obecny w zbiorze, jest instrukcją pustą i nie powoduje błędu.

       FD_CLR()
              Makro usuwa deskryptor pliku fd z zbioru set. Usunięcie  deskryptora  pliku,  który
              nie jest obecny w zbiorze jest instrukcją pustą i nie powoduje błędu.

       FD_ISSET()
              select()  modyfikuje  zawartość  zbiorów,  zgodnie  z  regułami opisanymi niżej. Po
              wywołaniu select(),  można  skorzystać  z  makra  FD_ISSET(),  aby  sprawdzić,  czy
              deskryptor  pliku jest wciąż obecny w zbiorze. FD_ISSET() zwraca wartość niezerową,
              jeśli deskryptor pliku fd jest obecny w zbiorze set i zero, gdy nie jest.

   Argumenty
       Argumenty select() są następujące:

       readfds
              Deskryptory pliku w tym zbiorze są monitorowane, aby sprawdzić, czy  są  gotowe  do
              odczytu. Deskryptor pliku jest gotowy do odczytu, jeśli operacja odczytu nie będzie
              blokowała; w szczególności, deskryptor pliku jest również gotowy na końcu pliku.

              Po powrocie select(), readfds  zostanie  wyczyszczone  ze  wszystkich  deskryptorów
              pliku, poza gotowymi do odczytu.

       writefds
              Deskryptory  pliku  w  tym zbiorze są monitorowane, aby sprawdzić, czy są gotowe do
              zapisu. Deskryptor pliku jest gotowy do zapisu, jeśli wszystkie operacje zapisu nie
              będą blokowały. Jednak nawet gdy deskryptor pliku jest wskazywany jako zapisywalny,
              duży zapis może wciąż blokować.

              Po powrocie select(), writefds zostanie  wyczyszczone  ze  wszystkich  deskryptorów
              pliku, poza gotowymi do zapisu.

       exceptfds
              Deskryptory   pliku   w   tym  zbiorze  są  monitorowane  pod  kątem  „szczególnych
              okoliczności”. Przykłady takich szczególnych  okoliczności  opisano  w  podręczniku
              poll(2) odnośnie POLLPRI.

              Po  powrocie  select(),  exceptfds zostanie wyczyszczone ze wszystkich deskryptorów
              pliku, poza tymi, dla których zaszły szczególne okoliczności.

       nfds   Argument ten powinien być ustawiony na najwyższy  numer  deskryptora  z  wszystkich
              trzech  zbiorów plus 1. Sprawdzany jest wskazany deskryptor pliku w każdym zbiorze,
              do tego limitu (lecz zob. USTERKI).

       timeout
              Argument timeout jest strukturą timeval  (pokazaną  niżej),  określającą  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() niezwłocznie  zakończy
              pracę (jest to przydatne przy odpytywaniu).

              Jeśli timeout jest równe NULL, select() może blokować w nieskończoność, czekając na
              gotowość deskryptora pliku.

   pselect()
       Wywołanie systemowe pselect() pozwala aplikacjom na  bezpieczne  oczekiwanie,  do  momentu
       uzyskania gotowości przez deskryptor plików lub do momentu przechwycenia sygnału.

       Funkcjonalność funkcji select() i pselect() jest identyczna, jeśli pominąć trzy różnice:

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

       •  Funkcja  select()  może  aktualizować  parametr  timeout,  aby  wskazać, jak dużo czasu
          minęło. Funkcja pselect() nie zmienia tego parametru.

       •  Funkcja select() nie  przyjmuje  parametru  sigmask  i  zachowuje  się,  jak  pselect()
          wywołane z NULL-em przekazanym w sigmask.

       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 (jeśli sigmask wynosi NULL, to maska sygnałów nie jest modyfikowana podczas
       wywołania pselect()).

       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
       Argument timeout do select() jest strukturą następującego typu:

           struct timeval {
               time_t      tv_sec;         /* sekundy */
               suseconds_t tv_usec;        /* mikrosekundy */
           };

       Odpowiadającym argumentem pselect() jest struktura timespec(3).

       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).
       Wartość zwracana może wynosić zero, jeśli czas oczekiwania upłynął zanim jakiś  deskryptor
       plików stał się gotowy.

       Po  błędzie zwracane jest -1 i ustawiane errno, wskazując 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). Zob. jednak BŁĘDY.

       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

       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.

STANDARDY

       POSIX.1-2008.

HISTORIA

       select()
              POSIX.1-2001, 4.4BSD (pojawiło się pierwotnie w 4.2BSD).

              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ą przeterminowania przed powrotem, ale wariant
              BSD tego nie robi.

       pselect()
              Linux 2.6.16.  POSIX.1g, POSIX.1-2001.

              Wcześniej był on emulowany w glibc (patrz również USTERKI).

       fd_set POSIX.1-2001.

UWAGI

       Następujący nagłówek zapewnia również typ fd_set: <sys/time.h>.

       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 działanie select() i pselect() nie wpływa znacznik O_NONBLOCK.

   Sztuczka „potoku do siebie”
       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.

   Emulowanie usleep(3)
       Przed powstaniem usleep(3) niektóre  programy  używały  wywołania  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ą.

   Relacja pomiędzy powiadomieniami select() i poll()
       W źródłach jądra Linux można znaleźć następujące  definicje  pokazujące  relację  pomiędzy
       powiadomieniami  o  warunkach:  odczytu,  zapisu  i  szczególnych okoliczności select(), a
       powiadomieniami zdarzeń zapewnianymi przez poll(2) i epoll(7):

           #define POLLIN_SET  (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN |
                                EPOLLHUP | EPOLLERR)
                              /* Gotowość do odczytu */
           #define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT |
                                EPOLLERR)
                              /* Gotowość do zapisu */
           #define POLLEX_SET  (EPOLLPRI)
                              /* Szczególne okoliczności */

   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  inny proces otworzy ponownie 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
       zbiorów do sprawdzenia z wartości nfds. Jednak w implementacji glibc, typ fd_set ma  stały
       rozmiar. Zob. też USTERKI.

       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 kernel_sigset_t *ss;   /* Wskaźnik do zestawu sygnałów */
               size_t ss_len;               /* Rozmiar (w bajtach) obiektu, na
                                               który wskazuje '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. Opis różnic pomiędzy podejściem jądra i libc do zestawu sygnałów
       znajduje się w podręczniku sigprocmask(2).

   Historyczne detale glibc
       glibc 2.0 dostarczała  niepoprawną  wersję  pselect(),  która  nie  przyjmowała  argumentu
       sigmask.

       Od  glibc  2.1  do  glibc  2.2.1  konieczne  było  zdefiniowanie  _GNU_SOURCE, aby uzyskać
       deklarację pselect() z <sys/select.h>.

USTERKI

       POSIX pozwala implementacji zdefiniować górny limit  zakresu  deskryptorów  plików,  które
       można  podać  w  zbiorze  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)  lub
       epoll(7).

       Implementacja  argumentów  fd_set  jako  argumentów wartość-wynik jest błędem projektowym,
       którego uniknięto w poll(2) i epoll(7).

       Zgodnie z POSIX, select() powinien sprawdzać wszystkie podane deskryptory pliku  w  trzech
       zbiorach  deskryptorów  pliku,  do  limitu  nfds-1.  Jednak bieżąca implementacja ignoruje
       wszelkie deskryptory pliku w  tych  zbiorach,  które  są  wyższe  od  maksymalnego  numeru
       aktualnie  otwartego  przez  proces  deskryptora  pliku.  Zgodnie  z  POSIX,  w  przypadku
       wystąpienia takiego deskryptora pliku w jednym z zbiorów, powinien wystąpić błąd EBADF.

       Od glibc 2.1, glibc dostarczała  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 Linuksie 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ŁADY

       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/select.h>

       int
       main(void)
       {
           int             retval;
           fd_set          rfds;
           struct timeval  tv;

           /* Obserwacja stdin (fd 0) i sprawdzanie kiedy ma wejście. */

           FD_ZERO(&rfds);
           FD_SET(0, &rfds);

           /* Czekanie do pięciu 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 pięciu 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), timespec(3), epoll(7), time(7)

       Samouczek z dyskusją i przykładami znajduje się w select_tut(2).

TŁUMACZENIE

       Autorami   polskiego   tłumaczenia   niniejszej   strony  podręcznika  są:  Przemek  Borys
       <pborys@dione.ids.pl>,   Robert    Luberda    <robert@debian.org>    i    Michał    Kułach
       <michal.kulach@gmail.com>

       Niniejsze  tłumaczenie  jest  wolną  dokumentacją. Bliższe informacje o warunkach licencji
       można   uzyskać   zapoznając   się   z   GNU   General   Public   License   w   wersji   3
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   lub   nowszej.   Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

       Błędy w tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej
       ⟨manpages-pl-list@lists.sourceforge.net⟩.