Provided by: manpages-fr_3.65d1p1-1_all bug

NOM

       aio - Vue d'ensemble des entrées-sorties (E/S) asynchrones POSIX

DESCRIPTION

       L'interface   d'E/S   asynchrones   (AIO  pour  « asynchronous  I/O »)  POSIX  permet  aux
       applications de déclencher une ou plusieurs opérations d'E/S réalisées de façon asynchrone
       (c'est-à-dire  en  arrière-plan).  La  fin  d'une  opération  d'E/S  peut  être notifiée à
       l'application de différentes façons au choix :  distribution  d'un  signal,  instanciation
       d'un thread ou absence de notification.

       L'interface AIO POSIX est composée des fonctions suivantes :

       aio_read(3)     Placer  en  file  d'attente  une  requête  de  lecture. C'est l'équivalent
                       asynchrone de read(2).

       aio_write(3)    Placer en  file  d'attente  une  requête  d'écriture.  C'est  l'équivalent
                       asynchrone de write(2).

       aio_fsync(3)    Placer   en  file  d'attente  une  requête  de  synchronisation  pour  des
                       opérations  d'E/S  sur  un  descripteur  de  fichier.  C'est  l'équivalent
                       asynchrone de fsync(2) et fdatasync(2).

       aio_error(3)    Obtenir l'état d'erreur d'une requête d'E/S placée en file d'attente.

       aio_return(3)   Obtenir l'état de retour d'une requête d'E/S terminée.

       aio_suspend(3)  Suspendre l'appelant jusqu'à la fin d'une ou plusieurs requêtes d'E/S d'un
                       ensemble indiqué.

       aio_cancel(3)   Essayer d'annuler des requêtes  d'E/S  en  cours  sur  un  descripteur  de
                       fichier indiqué.

       lio_listio(3)   Placer en file d'attente plusieurs requêtes d'E/S à partir d'un seul appel
                       de fonction.

       La structure aiocb (« asynchronous  I/O  control  block  »,  ou  bloc  de  contrôle  d'E/S
       asynchrones)  définit  les paramètres de contrôle d'une opération d'E/S. Un argument de ce
       type est utilisé avec toutes les fonctions précédentes. Cette structure est  de  la  forme
       suivante :

           #include <aiocb.h>

           struct aiocb {
               /* L'ordre de ces champs dépend de l'implémentation */

               int             aio_fildes;     /* Descripteur de fichier */
               off_t           aio_offset;     /* Position dans le fichier */
               volatile void  *aio_buf;        /* Emplacement du tampon */
               size_t          aio_nbytes;     /* Longueur de transfert */
               int             aio_reqprio;    /* Priorité de requête */
               struct sigevent aio_sigevent;   /* Méthode de notification */
               int             aio_lio_opcode; /* Opération à réaliser ;
                                                  lio_listio() seulement */

               /* Divers champs internes à l'implémentation ne sont pas montrés */
           };

           /* Codes opératoires pour « aio_lio_opcode » : */

           enum { LIO_READ, LIO_WRITE, LIO_NOP };

       Les champs de cette structure sont les suivants :

       aio_filedes     Le descripteur de fichier sur lequel les opérations d'E/S sont à réaliser.

       aio_offset      La position dans le fichier où les opérations d'E/S sont à réaliser.

       aio_buf         Le  tampon  utilisé pour le transfert de données des opérations de lecture
                       ou d'écriture.

       aio_nbytes      La taille du tampon pointé par aio_buf.

       aio_reqprio     Valeur à soustraire de la priorité temps-réel du thread de l'appelant pour
                       déterminer  la  priorité  d'exécution  de  cette  requête d'E/S (consultez
                       pthread_setschedparam(3)). La valeur indiquée doit  être  entre  0  et  la
                       valeur  renvoyée  par sysconf(_SC_AIO_PRIO_DELTA_MAX). Ce champ est ignoré
                       lors des opérations de synchronisation de fichier.

       aio_sigevent    Structure indiquant comment  l'appelant  sera  notifié  de  la  fin  d'une
                       opération  d'E/S  asynchrone.  Les  valeurs  de  aio_sigevent.sigev_notify
                       peuvent  être  SIGEV_NONE,   SIGEV_SIGNAL   et   SIGEV_THREAD.   Consultez
                       sigevent(7) pour plus de précisions.

       aio_lio_opcode  Le type d'opération à réaliser, utilisé seulement pour lio_listio(3).

       En  plus  des  fonctions standard précédentes, la bibliothèque C du projet GNU fournit les
       extensions suivantes à l'API AIO POSIX :

       aio_init(3)     Configurer les paramètres pour régler le comportement de  l'implémentation
                       AIO POSIX de la glibc.

ERREURS

       EINVAL Le  champ  aio_reqprio de la structure aiocb était inférieur à 0, ou supérieur à la
              limite renvoyée par l'appel sysconf(_SC_AIO_PRIO_DELTA_MAX).

VERSIONS

       Les interfaces AIO POSIX sont fournies par la glibc depuis la version 2.1.

CONFORMITÉ

       POSIX.1-2001, POSIX.1-2008.

NOTES

       Il est conseillé de mettre à  zéro  le  tampon  de  bloc  de  contrôle  avant  utilisation
       (consultez  memset(3)).  Le  tampon de bloc de contrôle et le tampon pointé par aio_buf ne
       doivent pas être modifiés pendant l'exécution d'une opération d'E/S. Ces  tampons  doivent
       rester valables jusqu'à la fin de l'opération d'E/S.

       Les  opérations  de  lecture  ou  d'écriture asynchrones simultanées qui utilisent la même
       structure aiocb produisent des résultats indéfinis.

       L'actuelle implémentation AIO POSIX de Linux est fournie  en  espace  utilisateur  par  la
       glibc.  De  nombreuses  limites  existent, en particulier le maintien de plusieurs threads
       pour  réaliser  des  opérations  d'E/S  est  très  coûteux  et  monte   mal   en   charge.
       L'implémentation d'E/S asynchrones basée sur l'état de la machine est en travaux depuis un
       moment sur le noyau (consultez  io_submit(2),  io_setup(2),  io_cancel(2),  io_destroy(2),
       io_getevents(2)),   mais  cette  implémentation  n'a  pas  encore  atteint  le  niveau  où
       l'implémentation AIO POSIX peut être entièrement réimplémentée  en  utilisant  les  appels
       système du noyau.

EXEMPLE

       Le  programme  suivant  ouvre  chaque fichier nommé en argument de sa ligne de commande et
       place une requête sur le  descripteur  de  fichier  dans  la  file  avec  aio_read(3).  Le
       programme  boucle  ensuite,  en  surveillant périodiquement toutes les opérations d'E/S en
       cours avec aio_error(3). Chaque requête d'E/S est configurée pour fournir une notification
       en  distribuant  un  signal.  Quand toutes les requêtes d'E/S sont terminées, le programme
       récupère leur état avec aio_return(3).

       Le signal SIGQUIT (créé en tapant Contrôle-\) provoque la demande d'annulation  de  chaque
       requête en cours avec aio_cancel(3).

       Voici un exemple de ce qui pourrait être affiché lors de l'exécution de ce programme. Dans
       cet exemple, le programme place en file d'attente deux requêtes sur l'entrée standard,  et
       deux lignes de saisie contenant « abc » et « x » y répondent.

           $ ./a.out /dev/stdin /dev/stdin
           /dev/stdin ouvert sur le descripteur 3
           /dev/stdin ouvert sur le descripteur 4
           aio_error():
               pour la requête 0 (descripteur 3) : En cours
               pour la requête 1 (descripteur 4) : En cours
           abc
           Signal de fin d'E/S reçu
           aio_error():
               pour la requête 0 (descripteur 3) : E/S réussie
               pour la requête 1 (descripteur 4) : En cours
           aio_error():
               pour la requête 1 (descripteur 4) : En cours
           x
           Signal de fin d'E/S reçu
           aio_error():
               pour la requête 1 (descripteur 4) : E/S réussie
           Toutes les requêtes d'E/S sont terminées
           aio_return():
               pour la requête 0 (descripteur 3) : 4
               pour la requête 1 (descripteur 4) : 2

   Source du programme

       #include <stdlib.h>
       #include <unistd.h>
       #include <stdio.h>
       #include <errno.h>
       #include <aio.h>
       #include <signal.h>

       #define BUF_SIZE 20     /* Taille des tampons pour les opérations de lecture */

       #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

       #define errMsg(msg)  do { perror(msg); } while (0)

       struct ioRequest {      /* Structure spécifique à l'application
                                  pour suivre les requêtes d'E/S */
           int           reqNum;
           int           status;
           struct aiocb *aiocbp;
       };

       static volatile sig_atomic_t gotSIGQUIT = 0;
                               /* Essayer d'annuler toutes les requêtes d'E/S
                                  en cours lors de la réception d'un SIGQUIT */

       static void             /* Gestionnaire pour SIGQUIT */
       quitHandler(int sig)
       {
           gotSIGQUIT = 1;
       }

       #define IO_SIGNAL SIGUSR1   /* Signal pour notifier la fin d'E/S */

       static void                 /* Gestionnaire pour le signal de fin d'E/S */
       aioSigHandler(int sig, siginfo_t *si, void *ucontext)
       {
           write(STDOUT_FILENO, "Signal de fin d'E/S reçu\n", 31);

           /* La structure ioRequest correspondante serait disponible en
                  struct ioRequest *ioReq = si->si_value.sival_ptr;
              et le descripteur de fichier serait alors disponible via
                  ioReq->aiocbp->aio_fildes */
       }

       int
       main(int argc, char *argv[])
       {
           struct ioRequest *ioList;
           struct aiocb *aiocbList;
           struct sigaction sa;
           int s, j;
           int numReqs;        /* Nombre total de requêtes d'E/S dans la file */
           int openReqs;       /* Nombre de requêtes d'E/S encore en cours */

           if (argc < 2) {
               fprintf(stderr, "Utilisation : %s <chemin> <chemin>...\n",
                       argv[0]);
               exit(EXIT_FAILURE);
           }

           numReqs = argc - 1;

           /* Allocation des tableaux */

           ioList = calloc(numReqs, sizeof(struct ioRequest));
           if (ioList == NULL)
               errExit("calloc");

           aiocbList = calloc(numReqs, sizeof(struct aiocb));
           if (aiocbList == NULL)
               errExit("calloc");

           /* Mise en place des gestionnaires pour SIGQUIT et le signal de fin d'E/S */

           sa.sa_flags = SA_RESTART;
           sigemptyset(&sa.sa_mask);

           sa.sa_handler = quitHandler;
           if (sigaction(SIGQUIT, &sa, NULL) == -1)
               errExit("sigaction");

           sa.sa_flags = SA_RESTART | SA_SIGINFO;
           sa.sa_sigaction = aioSigHandler;
           if (sigaction(IO_SIGNAL, &sa, NULL) == -1)
               errExit("sigaction");

           /* Ouverture de chaque fichier indiqué sur la ligne de commande, et mise en file
              d'attente d'une requête de lecture sur le descripteur de fichier correspondant */

           for (j = 0; j < numReqs; j++) {
               ioList[j].reqNum = j;
               ioList[j].status = EINPROGRESS;
               ioList[j].aiocbp = &aiocbList[j];

               ioList[j].aiocbp->aio_fildes = open(argv[j + 1], O_RDONLY);
               if (ioList[j].aiocbp->aio_fildes == -1)
                   errExit("open");
               printf("%s ouvert sur le descripteur %d\n", argv[j + 1],
                       ioList[j].aiocbp->aio_fildes);

               ioList[j].aiocbp->aio_buf = malloc(BUF_SIZE);
               if (ioList[j].aiocbp->aio_buf == NULL)
                   errExit("malloc");

               ioList[j].aiocbp->aio_nbytes = BUF_SIZE;
               ioList[j].aiocbp->aio_reqprio = 0;
               ioList[j].aiocbp->aio_offset = 0;
               ioList[j].aiocbp->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
               ioList[j].aiocbp->aio_sigevent.sigev_signo = IO_SIGNAL;
               ioList[j].aiocbp->aio_sigevent.sigev_value.sival_ptr =
                                       &ioList[j];

               s = aio_read(ioList[j].aiocbp);
               if (s == -1)
                   errExit("aio_read");
           }

           openReqs = numReqs;

           /* Boucle, surveillance de l'état des requêtes d'E/S */

           while (openReqs > 0) {
               sleep(3);       /* Délai entre chaque étape de surveillance */

               if (gotSIGQUIT) {

                   /* Lors de la réception de SIGQUIT, essayer d'annuler
                      toutes les requêtes d'E/S en cours, et afficher
                      l'état renvoyé par les requêtes d'annulation */

                   printf("réception de SIGQUIT ; annulation des requêtes d'E/S : \n");

                   for (j = 0; j < numReqs; j++) {
                       if (ioList[j].status == EINPROGRESS) {
                           printf("    Requête %d sur le descripteur %d :", j,
                                   ioList[j].aiocbp->aio_fildes);
                           s = aio_cancel(ioList[j].aiocbp->aio_fildes,
                                   ioList[j].aiocbp);
                           if (s == AIO_CANCELED)
                               printf("E/S annulée\n");
                           else if (s == AIO_NOTCANCELED)
                                   printf("E/S non annulée\n");
                           else if (s == AIO_ALLDONE)
                               printf("E/S terminée\n");
                           else
                               errMsg("aio_cancel");
                       }
                   }

                   gotSIGQUIT = 0;
               }

               /* Vérification de l'état de toutes les
                  requêtes d'E/S encore en cours */

               printf("aio_error():\n");
               for (j = 0; j < numReqs; j++) {
                   if (ioList[j].status == EINPROGRESS) {
                       printf("    pour la requête %d (descripteur %d) : ",
                               j, ioList[j].aiocbp->aio_fildes);
                       ioList[j].status = aio_error(ioList[j].aiocbp);

                       switch (ioList[j].status) {
                       case 0:
                           printf("E/S réussie\n");
                           break;
                       case EINPROGRESS:
                           printf("En cours\n");
                           break;
                       case ECANCELED:
                           printf("Annulée\n");
                           break;
                       default:
                           errMsg("aio_error");
                           break;
                       }

                       if (ioList[j].status != EINPROGRESS)
                           openReqs--;
                   }
               }
           }

           printf("Toutes les requêtes d'E/S sont terminées\n");

           /* Vérification de l'état de retour de toutes les requêtes d'E/S */

           printf("aio_return():\n");
           for (j = 0; j < numReqs; j++) {
               ssize_t s;

               s = aio_return(ioList[j].aiocbp);
               printf("    pour la requête %d (descripteur %d) : %zd\n",
                       j, ioList[j].aiocbp->aio_fildes, s);
           }

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       io_cancel(2), io_destroy(2), io_getevents(2), io_setup(2), io_submit(2), aio_cancel(3),
       aio_error(3), aio_init(3), aio_read(3), aio_return(3), aio_write(3), lio_listio(3)

       ⟨http://www.squid-cache.org/~adrian/Reprint-Pulavarty-OLS2003.pdf

COLOPHON

       Cette page fait partie de la publication 3.65 du projet man-pages Linux. Une description
       du projet et des instructions pour signaler des anomalies peuvent être trouvées à
       l'adresse http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
       <http://po4a.alioth.debian.org/> par l'équipe de traduction francophone au sein du projet
       perkamon <http://perkamon.alioth.debian.org/>.

       Veuillez signaler toute erreur de traduction en écrivant à
       <debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le paquet
       manpages-fr.

       Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la
       commande « man -L C <section> <page_de_man> ».