oracular (7) aio.7.gz

Provided by: manpages-fr_4.23.1-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 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(3type) 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).

STANDARDS

       POSIX.1-2008.

HISTORIQUE

       POSIX.1-2001. glibc 2.1.

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, "Gestionnaire pour le signal de fin d'E/S\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) {

                   /* 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 (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("    pour la requête %zu (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 (size_t j = 0; j < numReqs; j++) {
               ssize_t s;

               s = aio_return(ioList[j].aiocbp);
               printf("    pour la requête %zu (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⟩

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