Provided by: manpages-fr_3.32d0.2p4-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.

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.

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.

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) : %ld\n",
                       j, ioList[j].aiocbp->aio_fildes, (long) 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.32 du projet man-pages
       Linux. Une description du projet et des instructions pour signaler des
       anomalies peuvent être trouvées à l'adresse
       <URL:http://www.kernel.org/doc/man-pages/>.

TRADUCTION

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