Provided by: manpages-nl-dev_4.13-4_all 

NAAM
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - gelijktijdige In/Uit verdeling
SAMENVATTING
#include <sys/select.h>
int select(int nfds, fd_set *leesbi, fd_set *schrijfbi,
fd_set *uitzondbi, struct timeval *tijdslimiet);
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 *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *tijdslimiet,
const sigset_t *sigmask);
Test Macro´s in glibc (zie feature_test_macros(7)):
pselect(): _POSIX_C_SOURCE >= 200112L
BESCHRIJVING
select() staat een programma toe meerdere bestandsindicators te monitoren, het wacht totdat een of meer
bestandsindicators "gereed" worden voor een aantal klassen van Invoer/Uitvoer operaties (b.v. invoer
mogelijk). Een bestandsindicator wordt gereed geacht als het mogelijk is de overeenkomende Invoer/Uitvoer
operatie uit te voeren (b.v. read(2), of een voldoende kleine write(2)) zonder blokkering.
select() kan alleen bestandsindicator nummers monitoren die kleiner zijn dan FD_SETSIZE ; poll(2) en
epoll(7) hebben deze beperking niet. Zie BUGS.
Bestandsindicator verzamelingen
Het hoofdargument van select() zijn drie "verzamelingen" van bestandsindicators (gedeclareerd met het
type fd_set), dat de aanroeper toestaat te wachten op drie klassen van gebeurtenissen op de
gespecificeerde verzameling van bestandsindicators. Elk van de fd_set argumenten mag als NULL worden
opgegeven als geen bestandsindicators moeten in de gaten worden gehouden voor de overeenkomende klasse
van gebeurtenissen.
Let op: Bij terugkeer wordt elke bestandsindicator verzameling ter plekke gemodificeerd om aan te geven
welke bestandsindicator op dat moment "gereed" is. Daarom, als select() in een lus wordt gebruikt moeten
de verzamelingen geinitialiseerd worden voorafgaand aan elke aanroep. De implementatie van de fd_set
argumenten als waarde-resultaat argumenten is een ontwerp fout die werd vermeden in poll(2) epoll(7).
De inhoud van een bestandsindicator verzameling kan aangepast worden door de volgende macro´s te
gebruiken:
FD_ZERO()
Deze macro wist (verwijdert alle bestandsindicators van) verzameling. Hij moet worden gebruikt als
een eerste stap bij het initialiseren van een bestandsindicator verzameling.
FD_SET()
Deze macro voegt een bestandsindicator bi toe aan verzameling. Het toevoegen van een reeds
bestaande indicator aan een verzameling doet niets, en produceert geen fout.
FD_CLR()
Deze macro verwijderd een bestandsindicator bi van een verzameling. Het verwijderen van een
niet-aanwezige indicator in de verzameling doet niks, en produceert geen fout.
FD_ISSET()
select() modificeert de inhoud van verzamelingen volgens de hieronder beschreven regels. Na het
aanroepen van select() kan de FD_ISSET() macro worden gebruikt om te testen of een
bestandsindicator nog aanwezig is in de verzameling. FD_ISSET() retourneert niet-nul als de
bestandsindicator bi aanwezig is in verzameling, en nul als hij niet aanwezig is.
Argumenten
De argumenten van select() zij als volgt:
leesbi De bestandsindicators in deze verzameling worden bekeken om te zien of deze gereed zijn om te
lezen. Een bestandsindicator is gereed om te lezen als een lees operatie niet zal blokkeren; in
het bijzonder is een bestandsindicator ook gereed bij het bestand-einde.
Nadat select() is teruggekeerd zullen alle bestandsindicators in leesbi worden gewist behalve die,
die gereed zijn om te lezen.
schrijfbi
De bestandsindicators in deze verzameling worden bekeken om te zien of deze gereed zijn om te
schrijven. Een bestandsindicator is gereed om te schrijven als een schrijf operatie niet zal
blokkeren. Hoewel zelfs als een bestandsindicator aangeeft schrijfbaar te zijn, kan een grote
schrijfactie toch blokkeren .
Nadat select() is teruggekeerd zullen alle bestandsindicators in schrijfbi worden gewist behalve
die, die gereed zijn om te schrijven.
uitzondbi
De bestandsindicators in deze verzameling worden bekeken op "uitzonderlijke condities". Voor e
Nadat select() is teruggekeerd zullen alle bestandsindicators in uitzondbi worden gewist behalve
die, waarvoor een uitzonderlijke conditie is opgetreden.
nfds Dit argument dient gezet te worden op de hoogst-genummerde bestandsindicator in enige van de drie
verzamelingen, plus 1. De aangegeven bestandsindicators in elke verzameling worden gecontroleerd,
tot deze limiet (let op, zie BUGS).
tijdslimiet
Het tijdslimiet argument is een timeval structure (hieronder) die het interval specificeert dat
select() moet blokkeren terwijl hij wacht op een bestandsindicator om "gereed" te worden. De
aanroep zal blokkeren totdat ofwel:
• een bestandsindicator wordt gereed;
• een aanroep werd onderbroken door een signaal afhandelaar; of
• de tijdslimiet verliep.
Let op dat het tijdslimiet interval wordt afgerond op de systeem klok korrel, en de vertraging
door het schedulen van de kernel betekent dat het blokkeer interval kan worden overschreden met
een kleine hoeveelheid.
Als beide velden van de tijdslimiet structure nul zijn, dan keert select() meteen terug. (Dit is
bruikbaar om te pollen)
Als tijdslimiet werd opgegeven als NULL, dan wacht select() oneindig lang totdat een
bestandsindicator "gereed" wordt.
pselect()
De pselect() systeem aanroep staat een applicatie toe om veilig te wachten totdat een bestandsindicator
gereed wordt of een signaal wordt ontvangen.
De werking van select() en pselect() is identiek, anders dan deze drie verschillen:
• select() gebruikt een tijdslimiet welk een struct timeval (met seconden en microseconden) is, terwijl
pselect() een struct timespec is (met seconden en nanosecondsen).
• select() kan het tijdslimiet argument updaten om aan te geven hoeveel tijd er overbleef. pselect()
verandert dit argument niet.
• select() heeft geen sigmask argument en gedraagt zich als een pselect() aanroep met sigmask gelijk aan
NULL.
sigmask is een wijzer naar een signaal masker (zie sigprocmask(2)); als het niet NULL is, dan vervangt
pselect() eerst het huidige sigmaal masker door het masker aangewezen door sigmask, voert vervolgens de
"select" functie uit, en hersteld het het originele signaal masker. (Als sigmask is NULL, dan wordt het
signaal masker niet gewijzigd door de pselect() aanroep.
Anders dan het verschil in de precisie van het tijdslimiet argument, is de volgende pselect() aanroep:
ready = pselect(nfds, &readfds, &writefds, &exceptfds,
timeout, &sigmask);
equivalent aan het atomair uitvoeren van de volgende aanroepen:
sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
De reden dat pselect() nodig is, is dat als men wil wachten op ofwel een signaal of het "gereed" worden
van een bestandsindicator, dan voorkomt een atomaire test race-condities. (Veronderstel dat de signaal
afhandelaar een globale vlag zet en terug keert. Dan zou een test van deze globale vlag gevolgd door een
aanroep van select() oneindig lang hangen als het signaal precies na de test aankwam maar precies vóór de
aanroep. In tegenstelling hiermee staat pselect() toe om eerst het signaal te blokkeren, het ontvangen
signaal af te handelen, en dat pselect() aan te roepen, met het gewenste sigmask, daarmee de race te
voorkomen.
De tijdslimiet
Het tijdslimiet argument van select() is een structure van het volgende type:
struct timeval {
time_t tv_sec; /* seconden */
suseconds_t tv_usec; /* microseconden */
};
Het overeenkomende argument voor pselect() heeft het volgende type:
struct timespec {
time_t tv_sec; /* seconden */
long tv_nsec; /* nanoseconden */
};
Op Linux, wijzigt select() tijdslimiet om de niet geslapen tijd weer te geven; de meeste andere
implementaties doen dit niet. (POSIX.1 staat beide gedragingen toe.) Dit veroorzaakt problemen zowel
wanneer Linux code die tijdslimiet leest, wordt overgezet op andere besturingssystemen, als wanneer code
wordt overgezet naar Linux, die struct timeval hergebruikt voor meerdere select() in een lus zonder deze
te her-initialiseren. Beschouw tijdslimiet niet gedefinieerd nadat select terugkeert
EIND WAARDE
Bij succes geven select() en pselect() het aantal bestandsindicators terug die bevat zijn in de drie
geretourneerde indicator verzamelingen (dat is, het totaal aantal bits die gezet zijn in leesbi,
schrijfbi, uitzondbi). De uitvoer waarde mag nul zijn als de tijdslimiet verliep voordat een van de
indicators "gereed" werd.
Bij een fout wordt -1 teruggegeven en errno wordt overeenkomstig gezet; de bestandsindicators
verzamelingen blijven ongewijzigd en tijdslimiet wordt ongedefinieerd.
FOUTEN
EBADF Een ongeldige bestandsindicator werd opgegeven in een van de verzamelingen. (Misschien een
bestandsindicator die al gesloten werd, of een waarop een fout is opgetreden.) Hoewel, zie BUGS.
EINTR Een signaal werd gevangen; zie signal(7).
EINVAL nfds is negatief of overschrijdt de RLIMIT_NOFILE hulpbron limiet (zie getrlimit(2)).
EINVAL De waarde bevat in tijdslimiet is ongeldig.
ENOMEM Het was niet mogelijk om voldoende geheugen de bemachtigen voor interne tabellen.
VERSIES
pselect() werd toegevoegd aan Linux in kernel 2.6.16. Voordien werd pselect() geëmuleerd in glibc (maar
zie BUGS)
VOLDOET AAN
select() voldoet aan POSIX.1-2001, POSIX.1-2008, and 4.4BSD (select() verscheen eerst in 4.2BSD).
Algemeen overdraagbaar naar/van niet-BSD systemen daarbij de klonen met de BSD socket laag ondersteunend
(inclusief System V varianten). Let op dat de System V varianten typisch de tijdslimiet variabele zet
voor terugkeer, maar dat de BSD variant dit niet doet.
pselect() is gedefineerd in POSIX.1g, en in POSIX.1-2001 en POSIX.1-2008.
OPMERKINGEN
Als fd_set een vaste buffer grootte is. Uitvoeren van FD_CLR() of FD_SET() met een waarden van bi die
negatief is of groter of gelijk is aan FD_SETSIZE zal resulteren in onbepaald gedrag. Bovendien vereist
POSIX dat bi een geldige bestandsindicator is.
De werking van select() en pselect() wordt niet beïnvloed door de O_NONBLOCK vlag.
Op sommige andere UNIX systemen, kan select() falen met de fout EAGAIN als het systeem faalt om
kernel-interne hulpbronnen toe te kennen, in plaats van ENOMEM zoals Linux doet. POSIX specificeert deze
fout voor poll(2), maar niet voor select(). Overdraagbare programma´s controleren beter op EAGAIN en
lussen dan, net als bij EINTR.
De zelf-pijp truc
Op systemen waar pselect() ontbreekt, betrouwbare (en meer overdraagbare) signaal trapping kan worden
bereikt met de zelf-pijp truc. In deze truc schrijft een signaal afhandelaar een byte naar een pijp wiens
andere einde wordt gemonitord door select() in het hoofdprogramma. (Om blokkeren te voorkomen bij het
schrijven naar een volle pijp, of lezen van een lege pijp, dient niet-blokkerende Invoer/Uitvoer gebruikt
te worden bij het lezen van en schrijven naar een pijp.)
Emuleren usleep(3)
Voor het verschijnen van usleep(3) gebruikte sommige code de aanroep van select() met alle verzamelingen
leeg, nfds nul, en een niet-NULL tijdslimiet als een enigszins overdraagbare manier om met subseconde
precisie te slapen.
Overeenkomsten tussen select() en poll() meldingen
In de Linux kernel broncode vinden we de volgende definities die de overeenkomsten tussen de leesbare,
schrijfbare en uitzondering condities notificaties van select() tonen en de gebeurtenis notificaties
voorzien door poll(2) en epoll(7):
#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN |
EPOLLHUP | EPOLLERR)
/* Gereed om te lezen */
#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT |
EPOLLERR)
/* Gereed om te schrijven */
#define POLLEX_SET (EPOLLPRI)
/* Uitzondering conditie */
Multithreaded applicaties
Als een bestandsindicator die door select() wordt gemonitord wordt gesloten in een andere thread, dan is
het resultaat niet gespecificeerd. Op sommige UNIX systemen zal select() uit blokkeren gaan en terug
keren met een indicatie dat de bestandsindicator gereed is (een opvolgende Invoer/Uitvoer operatie zal
mogelijk falen met een fout, behalve als een ander proces de bestandsindicator heropent tussen het
tijdstip dat select() terug gaf en de Invoer/Uitvoer operatie werd uitgevoerd). Op Linux (en sommige
andere systemen) heeft het sluiten van de bestandsindicator in een andere thread geen effect op select().
Samenvattend: een applicatie die vertrouwt op een specifiek gedrag in dit scenario moet als buggy
beschouwd worden.
C library/kernel verschillen
De Linux kernel staat bestandsindicator verzamelingen van willekeurige grootte toe, waarbij de lengte van
de verzamelingen kan worden bepaald aan de hand van de waarde van nfds. Hoewel in de glibc implementatie
het type fs_set een vaste grootte heeft. Zie ook BUGS.
Het pselect() interface beschreven op deze pagina is geïmplementeerd in glibc. De onderliggende Linux
systeem aanroep is pselect6() genaamd. Deze systeem aanroep verschilt iet of wat in gedrag van de glibc
omwikkel functie.
De Linux pselect6() systeem aanroep verandert zijn tijdslimiet argument. Hoewel de glibc omwikkel functie
dit gedrag verbergt door het gebruik van een lokale variabele voor het timeout argument dat wordt door
gegeven aan de systeem aanroep. Dus modificeert de glibc pselect() functie zijn argument tijdslimiet
niet; dit gedrag wordt ook vereist door POSIX.1-2001.
Het laatste argument van de pselect6() systeem aanroep is geen sigset_t * wijzer, maar in plaats daarvan
een structure van de vorm:
struct {
const kernel_sigset_t *ss; /* Wijzer naar een signaal verzameling */
size_t ss_len; /* Grootte (in bytes) van het object
aangewezen door 'ss' */
};
Dit staat de systeem aanroep toe om zowel een wijzer naar de signaal verzameling als ook zijn grootte te
hebben, terwijl gelijkertijd wordt toegestaan op de meeste architecturen een maximum van 6 argumenten te
ondersteunen voor de systeem aanroep. Zie sigprocmask(2) voor een discussie over de verschillen tussen
de kernel en de libc notatie van de signaal verzameling.
Historische glibc details
Glibc 2.0 voorzag in een incorrecte versie van pselect() die niet om een sigmask argument vroeg.
In de glibc versies 2.1 tot 2.2.1 moest men _GNU_SOURCE definiëren om de declaratie van pselect() uit
<sys/select.h> te verkrijgen.
BUGS
POSIX staat een implementatie toe om een bovenlimiet te definiëren, die wordt geadverteerd door de
constante FD_SETSIZE, voor de het bereik van bestandsindicatoren dat kan worden opgegeven in een
bestandsindicator verzameling. De Linux kernel legt geen vaste limiet op, maar de glibc implementatie
maakt van fd_set een type van vaste grootte, met FD_SETSIZE gedefinieerd als 1024, en de FD_*() macro´s
werkend conform deze limiet. Om bestandsindicatoren te monitoren die groter dan deze limiet zijn, moet u
poll(2) of epoll(7) gebruiken.
Volgens POSIX zou select() alle opgegeven bestandsindicatoren in de drie bestandsindicatoren
verzamelingen moeten controleren, tot aan de limiet nfds-1. Hoewel de huidige implementatie elke
bestandsindicator in deze verzamelingen negeert die groter is dan het maximum bestandsindicator getal dat
het proces momenteel geopend heeft. Volgens POSIX zou elke bestandsindicator die werd opgegeven in een
van de verzamelingen moeten resulteren in de EBADF fout.
Vanaf versie 2.1 voorzag glibc in een emulatie van pselect() die werd geïmplementeerd gebruikmakend van
sigprocmask(2) en select(). Deze implementatie was gevoelig voor dezelfde race conditie waarvoor nu
precies pselect() ontworpen was om te voorkomen. Moderne versies van glibc gebruiken de (race-vrije)
pselect() systeem aanroep op kernels waarin deze is voorzien.
Op Linux kan select() een socket bestandsindicator rapporteren als "gereed om te lezen", terwijl
tegelijkertijd een opeenvolgende lees-actie blokkeert. Dit kan bijvoorbeeld optreden wanneer data werd
ontvangen maar bij het onderzoeken blijkt dat de controlesom verkeerd is en wordt verworpen. Er kunnen
andere omstandigheden zijn waarin bestandsindicatoren ten onrechte worden gerapporteerd als gereed. Het
kan daarom veiliger zijn om O_NONBLOCK te gebruiken op sockets die niet mogen blokkeren.
Op Linux wijzigt select() ook tijdslimiet als de aanroep werd onderbroken door een signaal afhandelaar
(m.a.w. de EINTR foutmelding). Dit wordt niet toegestaan door POSIX.1. De Linux pselect() systeem aanroep
heeft hetzelfde gedrag, maar de glibc omwikkel functie verstopt dit gedrag door de tijdslimiet intern te
kopiëren naar een lokale variabele en deze variabele door te geven naar de systeem aanroep.
VOORBEELDEN
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int
main(void)
{
fd_set lbesb;
struct timeval tw;
int terugwrd;
/* Beloer stdin (bi 0) om te kijken wanneer het invoer heeft. */
FD_ZERO(&lbesb);
FD_SET(0, &lbesb);
/* Wacht maximaal vijf seconden. */
tw.tv_sec = 5;
tw.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Vertrouw nu de waarde van tv niet! */
if (terugwrd == -1)
perror("select()");
else if (terugwrd)
printf("Gegevens zijn nu beschikbaar.\n");
/* FD_ISSET(0, &lbesb) zal waar zijn. */
else
printf("Geen gegevens binnen vijf seconden.\n");
exit(EXIT_SUCCESS);
}
ZIE OOK
accept(2), connect(2), poll(2), read(2), recv(2), restart_syscall(2), send(2), sigprocmask(2), write(2),
epoll(7), time(7)
Voor een inleiding met discussie en voorbeelden zie select_tut(2).
COLOFON
Deze pagina is onderdeel van release 5.10 van het Linux man-pages-project. Een beschrijving van het
project, informatie over het melden van bugs en de nieuwste versie van deze pagina zijn op
https://www.kernel.org/doc/man-pages/ te vinden.
VERTALING
De Nederlandse vertaling van deze handleiding is geschreven door Jos Boersema <joshb@xs4all.nl>, Mario
Blättermann <mario.blaettermann@gmail.com> en Luc Castermans <luc.castermans@gmail.com>
Deze vertaling is vrije documentatie; lees de GNU General Public License Version 3 of later over de
Copyright-voorwaarden. Er is geen AANSPRAKELIJKHEID.
Indien U fouten in de vertaling van deze handleiding zou vinden, stuur een e-mail naar debian-l10n-
dutch@lists.debian.org.
Linux 1 november 2020 SELECT(2)