Provided by: manpages-pl-dev_20051117-1_all bug

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)