table of contents
other sections
AIO(7) | Manuel du programmeur Linux | AIO(7) |
NOM¶
aio - Vue d'ensemble des entrées-sorties (E/S) asynchrones POSIXDESCRIPTION¶
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.- 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.
#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).
- 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.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).$ ./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)COLOPHON¶
Cette page fait partie de la publication 3.44 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> ».5 août 2012 | Linux |