table of contents
other sections
SELECT(2) | Podręcznik programisty Linuksa | SELECT(2) |
NAZWA¶
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchroniczne zwielokrotnianie wejście/wyjścieSKŁ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)):
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.
ready = pselect(nfds, &readfds, &writefds, &exceptfds, timeout, &sigmask);jest odpowiednikiem niepodzielnego wykonania następujących funkcji:
sigset_t origmask; sigprocmask(SIG_SETMASK, &sigmask, &origmask); ready = select(nfds, &readfds, &writefds, &exceptfds, timeout); sigprocmask(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ącostruct timeval { long tv_sec; /* sekundy */ long tv_usec; /* mikrosekundy */ };
struct timespec { long tv_sec; /* sekundy */ long tv_nsec; /* nanosekundy */ };
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; 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 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.struct timeval { time_t tv_sec; /* sekundy */ suseconds_t tv_usec; /* mikrosekundy */ };
Uwagi linuksowe¶
Wywołanie systemowe pselect() 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.BŁĘDY IMPLEMENTACJI¶
Glibc 2.0 dostarczała wersję pselect(), która nie przyjmowała argumentu sigmask.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¶
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), epoll(7), time(7)O STRONIE¶
Angielska wersja tej strony pochodzi z wydania 3.40 projektu Linux man-pages. Opis projektu oraz informacje dotyczące zgłaszania błędów 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> i Robert Luberda <robert@debian.org>. 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.40 oryginału.2010-08-31 | Linux |