Provided by: manpages-fr_4.15.0-9_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 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é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
       l'extension suivante à 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.

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

       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 <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 (int 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 (int 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ées\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 (int 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:
                           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 (int 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)

       "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.pdf⟩

COLOPHON

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

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>, 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⟩.