SELECT
Section: Manuel du programmeur Linux (2) Updated: 18 juillet 2003 Index
NOM
SYNOPSIS
DESCRIPTION
Délai maximal
VALEUR RENVOYÉE
ERREURS
NOTES
EXEMPLE
CONFORMITÉ
NOTES
VOIR AUSSI
TRADUCTION
NOM
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - Multiplexage d'entrées/sorties synchrones.
SYNOPSIS
/* D'après Posix 1003.1-2001 */
#include <sys/select.h>
/* D'après les standards précédents */
#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);
DESCRIPTION
Les fonctions
select
et
pselect
attendent des changements d'état sur plusieurs descripteurs de fichiers.
Elles ont un comportement identique, avec trois différences :
- (i)
-
La fonction
select
utilise un délai exprimé avec une
struct timeval
(secondes et microsecondes), alors que
pselect
utilise une
struct timespec
(secondes et nanosecondes).
- (ii)
-
La fonction
select
peut modifier le paramètre
timeout
pour indiquer le temps restant. La fonction
pselect
ne change pas ce paramètre.
- (iii)
-
La fonction
select
n'a pas de paramètre
sigmask
et se comporte comme
pselect
avec une valeur NULL pour
sigmask
Il y a trois ensembles indépendants de descripteurs surveillés simultanément.
Ceux de l'ensemble
readfds
seront surveillés pour vérifier si des caractères deviennent disponibles
en lecture. Plus précisément, on vérifie si un appel-système de lecture
ne bloquera pas - en particulier un descripteur en fin-de-fichier sera
considéré comme prêt. Les descripteurs de l'ensemble
writefds
seront surveillés pour vérifier si une écriture ne bloquera pas. Ceux de
exceptfds
seront surveillés pour l'occurrence de conditions exceptionnelles.
En sortie, les ensembles sont modifiés pour indiquer les descripteurs
qui ont changé de statut.
Quatre macros sont disponibles pour la manipulation des ensembles
FD_ZERO
efface un ensemble.
FD_SET
et
FD_CLR
ajoutent et suppriment un descripteur dans un ensemble.
FD_ISSET
vérifie si un descripteur est contenu dans un ensemble, principalement
utile après le retour de
select.
n
est le numéro du plus grand descripteur des 3 ensembles, plus 1.
timeout
est une limite supérieure au temps passé dans
select
avant son retour.
Elle peut être nulle, ce qui conduit
select
à revenir immédiatement. (Ce qui sert pour des surveillance en
polling).
Si le timeout est NULL (aucun),
select
peut bloquer indéfiniment.
sigmask
est un pointeur sur un masque de signaux (voir
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.
L'idée derrière
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 revienne. Alors un test de ce drapeaux, suivi d'un appel
select()
peut bloquer indéfiniment si le signal arrive juste après le test mais avant
l'appel. A l'inverse,
pselect
permet de bloquer le signal d'abord, traiter les signaux déjà reçus, puis
invoquer
pselect()
avec le
sigmask,
désiré, en évitant la situation de blocage).
Comme Linux n'a pas encore d'appel-système
pselect(),
la routine de la bibliothèque GlibC 2 contient encore le défaut.
Délai maximal
Les structures temporelles concernées sont définies dans
<sys/time.h>
comme ceci :
-
struct timeval {
long tv_sec; /* secondes */
long tv_usec; /* microsecondes */
};
et
-
struct timespec {
long tv_sec; /* secondes */
long tv_nsec; /* nanosecondes */
};
(However, see below on the POSIX 1003.1-2001 versions.)
Certaines applications appellent
select
nul, et un délai
timeout
non nul, afin d'endormir,
de manière portable,
le processus avec une précision plus fine que la seconde.
Sous Linux, la fonction
select
modifie
timeout
pour indiquer le temps restant mais la plupart des autres
implémentations ne le font pas.
Ceci 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 structure timeval 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 ensembles, qui peut être nul
si le délai de timeout a expiré avant que quoi que ce soit d'intéressant
ne se produise.
Ils retournent -1 s'ils échouent, auquel cas
errno
contient le code d'erreur.
ERREURS
- EBADF
-
Un descripteur de fichier (dans l'un des ensembles) est invalide.
- EINTR
-
Un signal a été intercepté.
- EINVAL
-
n
est négatif
- ENOMEM
-
Pas assez de mémoire pour le noyau.
NOTES
avec les trois ensembles vides,
n
EXEMPLE
#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;
/* Surveiller stdin (fd 0) en attente d'entrées */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Pendant 5 secondes maxi */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Considérer tv comme indéfini maintenant ! */
if (retval)
printf("Données disponibles maintenant\n");
/* FD_ISSET(0, &rfds) est vrai */
else
printf("Pas de données depuis 5 secondes\n");
return (0);
}
CONFORMITÉ
BSD 4.4 (la fonction
select
est apparue dans BSD 4.2). Généralement portable depuis ou vers des
systèmes non-BSD supportant des clones de la couche sockets BSD (y compris
les variantes du Système V).
Néanmoins, sachez que les variantes du système V fixent une variable de
timeout avant le retour alors que les variantes BSD ne le font pas.
La fonction
pselect
est définie dans IEEE Std 1003.1g-2000 (POSIX.1g) et pour partie dans
POSIX 1003.1-2001.
On la trouve dans GlibC 2.1 et ultérieure.
Glibc2.0 a une fonction de ce nom, mais sans le paramètre
sigmask.
NOTES
Un ensemble fd_set est un buffer 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 valide.
En ce qui concerne les types impliqués, la situation classique est que
les deux champs de la structure timeval soient des "long" (comme ci-dessous),
et que la structure soit définie dans
<sys/time.h>.
La situation avec POSIX 1003.1-2001 est
-
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
avec la structure définie dans
<sys/select.h>
et les types de données time_t et suseconds_t définis dans
<sys/types.h>.
Concernant les prototypes, on demande classiquement l'inclusion
de
<time.h>
pour
select.
Avec POSIX 1003.1-2001, on préfère inclure
<sys/select.h>
pour
select
et
pselect.
Les bibliothèques libc4 et libc5 n'avaient pas d'en-tête
<sys/select.h>,
mais avec les GlibC 2.0 et suivantes le fichier existe.
Pour la GlibC 2.0, le prototype de
pselect
est toujours erroné. Avec la
GlibC 2.1-2.2.1 le prototype de
pselect
est fourni si la constante
_GNU_SOURCE
est définie avant l'inclusion. Avec GlibC 2.2.2-2.2.4,
il faut que la constante
_XOPEN_SOURCE
soit définie avec une valeur supérieure ou égale à 600.
Quoiqu'il en soit, depuis POSIX 1003.1-2001, le bon prototype devrait être
défini par défaut.
VOIR AUSSI
TRADUCTION
Christophe Blaess, 1996-2003.
|