dwww Home | Manual pages | Find package

AIO(7)                 Miscellaneous Information Manual                 AIO(7)

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'équi-
              valent asynchrone de read(2).

       aio_write(3)
              Placer  en  file d'attente une requête d'écriture. C'est l'équi-
              valent 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'équi-
              valent 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'at-
              tente.

       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 */
           };

           /* Operation codes for 'aio_lio_opcode': */

           enum { LIO_READ, LIO_WRITE, LIO_NOP };

       Les membres de cette structure sont les suivants :

       aio_fildes
              Le descripteur du 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éa-
              liser.

       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'ap-
              pelant  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   sys-
              conf(_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_si-
              gevent.sigev_notify peuvent être SIGEV_NONE, SIGEV_SIGNAL et SI-
              GEV_THREAD. Consultez sigevent(7) pour plus de précisions.

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

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

       aio_init(3)
              Configurer les paramètres pour régler le comportement  de  l'im-
              plé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   sys-
              conf(_SC_AIO_PRIO_DELTA_MAX).

VERSIONS
       The POSIX AIO interfaces are provided by glibc since glibc 2.1.

STANDARDS
       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écu-
       tion 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 uti-
       lisateur  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_des-
       troy(2), io_getevents(2)), mais cette implémentation n'a pas encore at-
       teint le niveau où l'implémentation AIO POSIX peut être entièrement ré-
       implémentée en utilisant les appels système du noyau.

EXEMPLES
       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).

       The SIGQUIT signal (generated by typing control-\) causes  the  program
       to  request  cancelation  of  each  of  the  outstanding requests using
       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 <fcntl.h>
       #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)

       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)
       {
           if (si->si_code == SI_ASYNCIO) {
            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 sigaction sa;
           int s;
           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. */

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

           struct aiocb *aiocbList = calloc(numReqs, sizeof(*aiocbList));
           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 (size_t 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) {

                   /* On receipt of SIGQUIT, attempt to cancel each of the
                      outstanding I/O requests, and display status returned
                      from the cancelation requests. */

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

                   for (size_t j = 0; j < numReqs; j++) {
                       if (ioList[j].status == EINPROGRESS) {
                           printf("    Request %zu on descriptor %d:", j,
                                   ioList[j].aiocbp->aio_fildes);
                           s = aio_cancel(ioList[j].aiocbp->aio_fildes,
                                   ioList[j].aiocbp);
                           if (s == AIO_CANCELED)
                               printf("I/O canceled\n");
                           else if (s == AIO_NOTCANCELED)
                               printf("I/O not canceled\n");
                           else if (s == AIO_ALLDONE)
                               printf("I/O all done\n");
                           else
                               perror("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 (size_t j = 0; j < numReqs; j++) {
                   if (ioList[j].status == EINPROGRESS) {
                       printf("    for request %zu (descriptor %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:
                           perror("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 (size_t j = 0; j < numReqs; j++) {
               ssize_t s;

               s = aio_return(ioList[j].aiocbp);
               printf("    for request %zu (descriptor %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)

       "Asynchronous I/O Support in Linux 2.5", Bhattacharya, Pratt,
       Pulavarty, and Morgan, Proceedings of the Linux Symposium, 2003,
       ⟨https://www.kernel.org/doc/ols/2003/ols2003-pages-351-366.pdfTRADUCTION
       La traduction française de cette page de manuel a été créée par Chris-
       tophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <ste-
       phan.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.cou-
       lon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux
       <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centra-
       liens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <si-
       mon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@de-
       bian.org>, David Prévot <david@tilapin.org>, Thomas Vincent
       <tvincent@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
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ 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⟩.

Pages du manuel de Linux 6.03   5 février 2023                          AIO(7)

Generated by dwww version 1.15 on Sat Jun 29 01:49:39 CEST 2024.