Man page - fd_zero(3)

Packages contains this manual

Available languages:

en fr pl nl ja de

Manual

select

NOM
BIBLIOTHÈQUE
SYNOPSIS
DESCRIPTION
fd_set
Ensembles de descripteurs de fichier
Argument
pselect()
Délai
VALEUR RENVOYÉE
ERREURS
VERSIONS
STANDARDS
HISTORIQUE
NOTES
L’astuce du « self-pipe »
Émuler usleep(3)
Correspondance entre les notifications de select() et de poll()
Programmes multithreadés
Différences entre bibliothÚque C et noyau
Détails historiques sur la glibc
BOGUES
EXEMPLES
VOIR AUSSI
TRADUCTION

NOM

select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO, fd_set - Multiplexage d’entrĂ©es-sorties synchrones

BIBLIOTHÈQUE

BibliothĂšque C standard ( libc , -lc )

SYNOPSIS

#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 );

Exigences de macros de test de fonctionnalités pour la glibc (consulter feature_test_macros (7)) :

pselect () :
_POSIX_C_SOURCE >= 200112L

DESCRIPTION

Attention : select () ne peut surveiller que des descripteurs de fichier dont le numĂ©ro est infĂ©rieur Ă  FD_SETSIZE (1024) — une limite excessivement basse pour beaucoup d’applications modernes — et cette limite ne changera pas. Toutes les applications modernes devraient utiliser Ă  la place poll (2) ou epoll (7) qui ne souffrent pas de cette limitation.

select () permet Ă  un programme de surveiller plusieurs descripteurs de fichier, en attendant qu’au moins l’un de ces descripteurs soit « prĂȘt » pour une certaine classe d’opĂ©rations d’entrĂ©e-sortie (par exemple une entrĂ©e est possible). Un descripteur de fichier est considĂ©rĂ© comme prĂȘt s’il est possible d’effectuer l’opĂ©ration correspondante (par exemple read (2) ou un write (2) assez petit) sans bloquer.

fd_set

Un type de structure qui peut représenter un ensemble de descripteurs de fichier. Selon POSIX, le nombre maximal de descripteurs de fichier dans une structure fd_set est la valeur de la macro FD_SETSIZE .

Ensembles de descripteurs de fichier

Les paramĂštres principaux de select () sont trois « ensembles » de descripteurs de fichier (dĂ©clarĂ©s avec le type fd_set ), qui permettent Ă  l’appelant d’attendre trois classes d’évĂ©nements sur l’ensemble de descripteurs de fichier indiquĂ©. Chacun des paramĂštres de fd_set peut ĂȘtre indiquĂ© comme NULL si aucun descripteur de fichier ne doit ĂȘtre surveillĂ© pour la classe d’évĂ©nements correspondante.

Important : lors de la sortie, chacun des ensembles de descripteurs de fichier est modifiĂ© sur place pour indiquer quels descripteurs de fichier sont actuellement « prĂȘts ». Par consĂ©quent, si on utilise select () dans une boucle, les ensembles doivent ĂȘtre rĂ©initialisĂ©s avant chaque appel.

Le contenu d’un ensemble de descripteurs de fichier peut ĂȘtre manipulĂ© en utilisant les macros suivantes :
FD_ZERO
()

Cette macro efface (supprime tous les descripteurs de fichier) set . Elle doit ĂȘtre utilisĂ©e en tant que premiĂšre Ă©tape de l’initialisation d’un ensemble de descripteurs de fichier.

FD_SET ()

Cette macro ajoute le descripteur de fichier fd Ă  set . L’ajout d’un descripteur de fichier dĂ©jĂ  prĂ©sent dans l’ensemble est sans effet et ne produit pas d’erreur.

FD_CLR ()

Cette macro supprime le descripteur de fichier fd de set . La suppression d’un descripteur de fichier non prĂ©sent dans l’ensemble est sans effet et ne produit pas d’erreur.

FD_ISSET ()

select () modifie le contenu des ensembles en fonction des rĂšgles dĂ©crites ci-dessous. AprĂšs un appel Ă  select (), la macro FD_ISSET () peut ĂȘtre utilisĂ©e pour tester si un descripteur de fichier est prĂ©sent dans un ensemble. FD_ISSET () ne renvoie pas zĂ©ro si le descripteur de fichier fd est prĂ©sent dans set , sinon il le renvoie.

Argument

Les paramÚtres de select () sont les suivants :
readfds

Les descripteurs de fichier de cet ensemble sont surveillĂ©s pour voir s’ils sont prĂȘts en lecture. Un descripteur de fichier est prĂȘt si une opĂ©ration de lecture ne bloquera pas ; en particulier, le descripteur de fichier est prĂȘt sur une fin-de-fichier.

AprĂšs que select () ait renvoyĂ©, readfds sera vidĂ© de tous les descripteurs de fichier sauf ceux prĂȘts en lecture.

writefds

Les descripteurs de fichier de cet ensemble sont surveillĂ©s pour voir s’ils sont prĂȘts en Ă©criture. Un descripteur de fichier est prĂȘt si une opĂ©ration d’écriture ne bloquera pas. Cependant, mĂȘme si un descripteur de fichier est indiquĂ© comme inscriptible, une Ă©criture abondante peut toujours bloquer.

AprĂšs que select () ait renvoyĂ©, writefds () sera vidĂ© de tous les descripteurs de fichier, sauf ceux prĂȘts en Ă©criture.

exceptfds

Les descripteurs de fichier de cet ensemble sont surveillés en cas de « conditions exceptionnelles ». Pour des exemples de conditions exceptionnelles, voir le point sur POLLPRI dans poll (2).

AprĂšs que select () ait renvoyĂ©, exceptfds () sera vidĂ© de tous les descripteurs de fichier, sauf ceux oĂč s’est produite une condition exceptionnelle.

nfds

Ce paramĂštre doit ĂȘtre positionnĂ© sur le numĂ©ro du plus grand descripteur des trois ensembles, plus 1 . Les descripteurs de fichier indiquĂ©s dans chaque ensemble sont vĂ©rifiĂ©s dans cette limite (mais voir BOGUES).

timeout

L’argument timeout est une structure timeval (dĂ©crite ci-dessous) qui prĂ©cise la durĂ©e de l’intervalle pendant lequel select () restera bloquĂ© dans l’attente d’un descripteur de fichier disponible. L’appel restera bloquĂ© jusqu’à :

-

un descripteur de fichier devient prĂȘt ;

-

l’appel est interrompu par un gestionnaire de signal ;

-

le délai expire.

Notez que l’intervalle timeout est arrondi selon la granularitĂ© de l’horloge du systĂšme, et un retard d’ordonnancement du noyau peut entraĂźner un lĂ©ger dĂ©passement de la durĂ©e de blocage.

Si les deux champs de la structure timeval valent zĂ©ro, select () renvoie immĂ©diatement (c’est utile pour la scrutation).

Si timeout est indiquĂ© comme Ă©tant NULL, select () restera bloquĂ© dans l’attente d’un descripteur de fichier disponible :

pselect()

L’appel systĂšme pselect () permet Ă  une application d’attendre de maniĂšre sĂ©curisĂ©e un signal ou qu’un descripteur de fichier soit prĂȘt.

select () et pselect () ont un comportement identique, avec trois différences :

-

La fonction select () utilise un délai exprimé avec une struct timeval (en secondes et microsecondes), alors que pselect () utilise une struct timespec (en secondes et nanosecondes).

-

La fonction select () peut modifier le paramĂštre timeout pour indiquer le temps restant. La fonction pselect () ne change pas ce paramĂštre.

-

La fonction select () n’a pas de paramùtre sigmask et se comporte comme pselect () avec une valeur NULL pour sigmask

sigmask est un pointeur sur un masque de signaux (consultez sigprocmask (2)). S’il n’est pas NULL, alors pselect () remplace d’abord le masque de signaux en cours par celui indiquĂ© dans sigmask , puis invoque la fonction « select », et enfin restaure le masque de signaux Ă  nouveau (si sigmask est NULL, le masque de signaux n’est pas modifiĂ© pendant l’appel pselect ()).

Mise Ă  part la diffĂ©rence de prĂ©cision de l’argument timeout , l’appel pselect () suivant :

ready = pselect(nfds, &readfds, &writefds, &exceptfds,
timeout, &sigmask);

est équivalent à exécuter de façon atomique les appels suivants :

sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);

La raison de la prĂ©sence de pselect () est que pour l’attente d’un Ă©vĂ©nement, que ce soit un signal ou une condition sur un descripteur, un test atomique est nĂ©cessaire pour Ă©viter les situations de concurrence. (Supposons que le gestionnaire de signaux active un drapeau global et renvoie. Alors un test de ce drapeau, suivi d’un appel select () peut bloquer indĂ©finiment si le signal arrive juste aprĂšs le test mais avant l’appel. À l’inverse, pselect () permet de bloquer les signaux d’abord, traiter les signaux dĂ©jĂ  reçus, puis invoquer pselect () avec le sigmask dĂ©sirĂ©, en Ă©vitant la situation de concurrence.)

Délai

Le paramÚtre timeout de select () est une structure du type suivant :

struct timeval {
time_t tv_sec; /* secondes */
suseconds_t tv_usec; /* microsecondes */
};

Le paramĂštre correspondant Ă  pselect () est une structure timespec (3).

Sous Linux, la fonction select () modifie timeout pour indiquer le temps non endormi ; la plupart des autres implĂ©mentations ne le font pas (POSIX.1 autorise les deux comportements). Cela pose des problĂšmes Ă  la fois pour porter sur d’autres systĂšmes du code dĂ©veloppĂ© sous Linux qui utilise cette valeur de timeout modifiĂ©e, et pour porter sous Linux du code qui rĂ©utilise plusieurs fois la struct timeval pour plusieurs select ()s dans une boucle sans la rĂ©initialiser. La meilleure attitude Ă  adopter est de considĂ©rer timeout comme indĂ©fini aprĂšs le retour de select ().

VALEUR RENVOYÉE

En cas de rĂ©ussite select () et pselect () renvoient le nombre de descripteurs dans les trois ensembles de descripteurs renvoyĂ©s (c’est-Ă -dire le nombre total de bits dĂ©finis dans readfds , writefds et exceptfds ) qui peut ĂȘtre nul si le dĂ©lai d’expiration a Ă©tĂ© atteint avant qu’un descripteur de fichier ne soit prĂȘt.

En cas d’erreur, la valeur de retour est -1 et errno est dĂ©finie pour prĂ©ciser l’erreur ; les ensembles de descripteurs de fichiers ne sont pas modifiĂ©s et timeout devient indĂ©fini.

ERREURS

EBADF

Un descripteur de fichier non valable Ă©tait dans l’un des ensembles (peut-ĂȘtre un descripteur dĂ©jĂ  fermĂ© ou sur lequel une erreur s’est produite).Cependant, consultez BOGUES

EINTR

Un signal a été intercepté ; consultez signal (7).

EINVAL

nfds est négatif ou dépasse la limite de ressource RLIMIT_NOFILE (voir getrlimit (2)).

EINVAL

La valeur contenue dans timeout n’est pas valable.

ENOMEM

IncapacitĂ© d’allouer de la mĂ©moire pour des tables internes.

VERSIONS

Sur d’autres systĂšmes UNIX, select () peut Ă©chouer avec l’erreur EAGAIN si le systĂšme ne parvient pas Ă  allouer des ressources internes du noyau contrairement Ă  l’erreur ENOMEM de Linux. POSIX spĂ©cifie cette erreur pour poll (2) mais pas pour select (2). Des programmes portables peuvent souhaiter vĂ©rifier EAGAIN et la boucle comme avec EINTR .

STANDARDS

POSIX.1-2008.

HISTORIQUE

select ()

POSIX.1-2001, 4.4BSD (apparu dans 4.2BSD).

Généralement portable depuis ou vers des systÚmes non BSD gérant des clones de la couche sockets BSD (y compris les variantes de System V). Sachez néanmoins, que les variantes de System V définissent la variable timeout avant le retour alors que les variantes BSD ne le font pas.

pselect ()

Linux 2.6.16. POSIX.1g, POSIX.1-2001.

Précédemment, il était émulé dans la glibc (mais voir la section BOGUES).

fd_set

POSIX.1-2001.

NOTES

L’en-tĂȘte suivant fournit aussi le type fd_set : <sys/time.h> .

Un ensemble fd_set est un tampon de taille fixe. Exécuter FD_CLR () ou FD_SET () avec fd négatif ou supérieur ou égal à FD_SETSIZE résultera en un comportement indéfini. Plus encore, POSIX demande que fd soit un descripteur de fichier valable.

Les opĂ©rations select () et pselect () ne sont pas concernĂ©es par l’attribut O_NONBLOCK .

L’astuce du « self-pipe »

Sur les systĂšmes sans pselect , une gestion plus sĂ»re (et plus portable) des signaux peut ĂȘtre obtenue en utilisant l’astuce du « self-pipe » : un gestionnaire de signal Ă©crit un octet dans un tube dont select () dans le programme principal surveille l’autre extrĂ©mitĂ©. (Pour Ă©viter la possibilitĂ© de blocage lors de l’écriture dans un tube pouvant ĂȘtre plein ou de la lecture dans un tube pouvant ĂȘtre vide, des entrĂ©es et sorties non bloquantes sont utilisĂ©es pour la lecture et l’écriture dans le tube.)

Émuler usleep(3)

Avant l’arrivĂ©e de usleep (3), certaines applications appelaient select () avec trois ensembles de descripteurs vides, nfds nul et un dĂ©lai timeout non NULL, afin d’endormir, de maniĂšre portable, le processus avec une prĂ©cision plus fine que la seconde.

Correspondance entre les notifications de select() et de poll()

Dans les sources du noyau Linux, nous trouvons les dĂ©finitions suivantes qui montrent la correspondance entre les notifications de lisibilitĂ©, d’inscriptibilitĂ© et de condition exceptionnelle de select () et les notifications d’évĂ©nements fournies par poll (2) et epoll (7) :

#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN |
EPOLLHUP | EPOLLERR)
/* PrĂȘt en lecture */
#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT |
EPOLLERR)
/* PrĂȘt en Ă©criture */
#define POLLEX_SET (EPOLLPRI)
/* Condition exceptionnelle */

Programmes multithreadés

Si un descripteur de fichier surveillĂ© par select () est fermĂ© dans un autre thread, le rĂ©sultat est indĂ©terminĂ©. Sur certains systĂšmes UNIX, select () dĂ©bloque et termine, avec une indication que le descripteur de fichier est prĂȘt (une opĂ©ration entrĂ©e/sortie ultĂ©rieure risque d’échouer avec une erreur, sauf si le descripteur de fichier a Ă©tĂ© rĂ©ouvert entre le moment oĂč select () termine et l’exĂ©cution des opĂ©rations entrĂ©e/sortie). Sur Linux (et d’autres systĂšmes), la fermeture du descripteur de fichier dans un autre thread n’a aucun effet sur select (). En rĂ©sumĂ©, toute application qui s’appuie sur un comportement particulier dans ce scĂ©nario doit ĂȘtre considĂ©rĂ©e comme boguĂ©e.

Différences entre bibliothÚque C et noyau

Le noyau Linux autorise les ensembles de descripteurs de fichier de n’importe quelle taille, en dĂ©terminant la taille des ensembles Ă  vĂ©rifier Ă  partir de la valeur de nfds . Cependant, dans l’implĂ©mentation de la glibc, le type fd_set a une taille fixe. Voir aussi les BOGUES.

L’interface pselect () dĂ©crite dans cette page est implĂ©mentĂ©e par la glibc. L’appel systĂšme Linux sous-jacent est appelĂ© pselect6 (). Cet appel systĂšme a un comportement quelque peu diffĂ©rent de la fonction d’enveloppe de la glibc.

L’appel systĂšme pselect6 () de Linux modifie son argument timeout . Cependant, la fonction d’enveloppe de la glibc cache ce comportement en utilisant une variable locale pour l’argument timeout qui est passĂ© Ă  l’appel systĂšme. Par consĂ©quent, la fonction pselect () de la glibc ne modifie pas son paramĂštre timeout , ce qui est le comportement prescrit par POSIX.1-2001.

Le dernier argument de l’appel systùme pselect6 () n’est pas un pointeur sigset_t * , mais une structure de la forme suivante :

struct {
const kernel_sigset_t *ss; /* Pointeur vers un ensemble de signaux */
size_t ss_len; /* Taille (en octets) de l’objet vers
lequel pointe 'ss' */
};

Cela permet Ă  l’appel systĂšme d’obtenir Ă  la fois le pointeur vers l’ensemble de signaux et sa taille, tout en permettant Ă  la plupart des architectures de ne prendre en charge qu’un maximum de 6 arguments pour un appel systĂšme. Voir sigprocmask (2) pour un point sur la diffĂ©rence entre la vision du noyau et celle de la libc de l’ensemble de signaux.

Détails historiques sur la glibc

La glibc 2.0 fournissait une mauvaise version de pselect () qui n’avait pas d’argument sigmask .

De la glibc 2.1 Ă  la glibc 2.2.1, on peut dĂ©finir _GNU_SOURCE afin d’obtenir la dĂ©claration de pselect () depuis <sys/select.h> .

BOGUES

POSIX autorise une implĂ©mentation Ă  dĂ©finir une limite supĂ©rieure indiquĂ©e Ă  l’aide de la constante FD_SETSIZE , dans l’intervalle de descripteurs de fichier qui peuvent ĂȘtre indiquĂ©s dans un ensemble de descripteurs de fichier. Le noyau Linux n’impose pas de limite fixe mais l’implĂ©mentation de la glibc fait que fd_set est un type de taille fixe, oĂč FD_SETSIZE est dĂ©fini Ă  1024 et oĂč les macros FD_* () agissent en fonction de cette limite. Pour surveiller des descripteurs de fichier supĂ©rieurs Ă  1023, utilisez plutĂŽt poll (2) ou epoll (7).

L’implĂ©mentation des paramĂštres de fd_set en tant qu’arguments valeur-rĂ©sultat est une erreur de conception qui est Ă©vitĂ©e dans poll (2) et epoll (7).

Selon POSIX, select () devrait vĂ©rifier tous les descripteurs de fichier des trois ensembles jusqu’à nfds-1 . Cependant, l’implĂ©mentation actuelle ignore tout descripteur de fichier dans ces ensembles supĂ©rieur au numĂ©ro le plus Ă©levĂ© de descripteur de fichier que le processus a ouvert. Selon POSIX, un tel descripteur de fichier indiquĂ© dans l’un des ensembles devrait provoquer une erreur EBADF .

À partir de la glibc 2.1, la glibc fournissait une Ă©mulation de pselect () implĂ©mentĂ©e avec sigprocmask (2) et select (). Cette implĂ©mentation Ă©tait vulnĂ©rable Ă  la condition de concurrence que pselect () Ă©tait conçu pour Ă©viter. Les versions rĂ©centes de la glibc utilisent l’appel systĂšme pselect () (sans risque de concurrence) si le noyau le fournit.

Sous Linux, select () peut signaler un descripteur de fichier socket comme « prĂȘt Ă  lire » alors qu’une lecture suivante bloque. Cela peut, par exemple, survenir lorsque des donnĂ©es sont arrivĂ©es mais, aprĂšs vĂ©rification, ont une mauvaise somme de contrĂŽle et sont rejetĂ©es. Cela peut Ă©galement arriver dans d’autres circonstances dans lesquelles le descripteur de fichier est faussement signalĂ© comme prĂȘt. Aussi, il est plus sĂ»r d’utiliser O_NONBLOCK sur des sockets qui ne devraient pas bloquer.

Sous Linux, select () modifie Ă©galement timeout si l’appel est interrompu par un gestionnaire de signaux (code d’erreur EINTR ). Cela est interdit par POSIX.1. L’appel systĂšme pselect () de Linux se comporte de la mĂȘme façon, mais la glibc cache cette particularitĂ© en copiant timeout vers une variable locale et en passant cette variable Ă  l’appel systĂšme.

EXEMPLES

#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int
main(void)
{
int retval;
fd_set rfds;
struct timeval tv;
/* Surveiller stdin (fd 0) en attente d’entrĂ©es. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Attendre jusqu’à 5 secondes. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Ne pas s’appuyer sur la valeur de tv maintenant ! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Des données sont disponibles maintenant\n");
/* FD_ISSET(0, &rfds) est alors vrai. */
else
printf("Aucune donnée durant les cinq secondes.\n");
exit(EXIT_SUCCESS);
}

VOIR AUSSI

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)

Pour un tutoriel avec des exemples, consultez select_tut (2).

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Cédric Boutillier <cedric.boutillier@gmail.com>, Frédéric Hantrais <fhantrais@gmail.com>, Jean-Philippe MENGUAL <jpmengual@debian.org> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n’y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org .