Quel est le statut des E/S asynchrones POSIX (AIO)?

Il y a des pages dispersées sur le web qui décrivent les installations POSIX AIO avec plus ou moins de détails. Aucun d'entre eux n'est terriblement récent. Il n'est pas clair ce qui, exactement, ils les décrivent. Par exemple, le "Officiel" (?) site web pour le noyau Linux support d'E/S asynchrones ici dit que les sockets ne fonctionnent pas, mais le " aio.les pages de manuel h" sur mon poste de travail Ubuntu 8.04.1 semblent toutes impliquer que cela fonctionne pour des descripteurs de fichiers arbitraires. Ensuite, il y a un autre projet qui semble fonctionner à la couche de bibliothèque avec encore moins de documentation.

J'aimerais savoir:

  • Quel est le but de POSIX AIO? Étant donné que l'exemple le plus évident d'une implémentation que je peux trouver dit qu'il ne supporte pas les sockets, le tout me semble bizarre. Est-ce juste pour les e / s de disque asynchrone? Si oui, pourquoi L'API hyper-générale? Sinon, pourquoi les E/S disque sont-elles la première chose qui a été attaquée?
  • où y a-t-il un exemple complete POSIX AIO programmes que je peux regarder?
  • est-ce que quelqu'un l'utilise réellement, pour de vrai?
  • quelles plates-formes prennent en charge POSIX AIO? Quelles parties de celui-ci soutiennent-ils? Est-ce que quelqu'un supporte vraiment le "Any I/O to any FD" implicite que <aio.h> semble promettre?

Les autres mécanismes de multiplexage à ma disposition sont parfaitement bons, mais les fragments aléatoires d'informations flottant là-bas m'ont rendu curieux.

89
demandé sur Glyph 2008-09-18 01:32:25

4 réponses

Les E / S réseau ne sont pas une priorité pour AIO car tous ceux qui écrivent des serveurs réseau POSIX utilisent une approche non bloquante basée sur les événements. L'ancienne approche Java "milliards de threads bloquants" suce horriblement.

Les e / s D'écriture de disque sont déjà mises en mémoire tampon et les e/s de lecture de disque peuvent être pré-extraites en mémoire tampon à l'aide de fonctions telles que posix_fadvise. Cela laisse des e / s de disque directes et non tamponnées comme le seul but utile pour AIO.

Les e/s directes sans tampon ne sont vraiment utiles que pour les transactions les bases de données, et celles-ci ont tendance à écrire leurs propres threads ou processus pour gérer leurs e/s de disque

Donc, à la fin cela laisse POSIX AIO dans la position de ne pas servir tout but utile. Ne l'utilisez pas.

24
répondu Zan Lynx 2008-09-17 23:15:51

Faire des e/s socket efficacement a été résolu avec KQueue, epoll, ports d'achèvement IO et autres. Faire des e / s de fichiers asynchrones est une sorte de retard (à part les e/s superposées de windows et le support précoce de solaris pour posix AIO).

Si vous cherchez à faire des e/s socket, vous feriez probablement mieux d'utiliser l'un des mécanismes ci-dessus.

Le but principal D'AIO est donc de résoudre le problème des e / s de disque asynchrones. les fichiers réguliers, et non les sockets (puisque kqueue le fait tellement mieux de toute façon).

Les opérations D'écriture sont généralement mises en cache par le noyau et vidées ultérieurement. Par exemple, lorsque la tête de lecture du lecteur passe par l'emplacement où le bloc doit être écrit.

Cependant, pour les opérations de lecture, si vous voulez que le noyau priorise et ordonne vos lectures, AIO est vraiment la seule option. Voici pourquoi le kernal peut (théoriquement) le faire mieux que n'importe quel niveau d'utilisateur application:

  • le noyau voit toutes les e / s de disque, pas seulement les tâches de disque de vos applications, et peut les commander à un niveau global
  • le noyau (peut) savoir où se trouve la tête de lecture du disque, et peut choisir les tâches de lecture que vous lui transmettez dans un ordre optimal, pour déplacer la tête la plus courte distance
  • le noyau peut profiter de mise en file d'attente des commandes natives pour optimiser davantage vos opérations de lecture
  • Vous pouvez être en mesure d'émettre plus d'opérations de lecture par appel système utilisant lio_listio () qu'avec readv (), surtout si vos lectures ne sont pas (logiquement) contiguës, économisant un tout petit peu de surcharge d'appel système.
  • Votre programme peut être légèrement plus simple avec AIO puisque vous n'avez pas besoin d'un thread supplémentaire pour bloquer un appel en lecture ou en écriture.

Cela dit, posix AIO a une interface assez maladroite, par exemple:

  • la seule moyenne efficace et bien prise en charge des rappels d'événements sont via des signaux, ce qui le rend difficile à utiliser dans un bibliothèque, car cela signifie utiliser les numéros de signal de l'espace de noms de signal global de processus. Si votre système D'exploitation ne prend pas en charge les signaux en temps réel, cela signifie également que vous devez parcourir toutes vos demandes en suspens pour déterminer laquelle est réellement terminée (c'est le cas pour Mac OS X Par exemple, pas Linux). Attraper des signaux dans un environnement multi-thread rend également certaines restrictions difficiles. Vous pouvez généralement pas réagir à l'événement à l'intérieur du gestionnaire de signal, mais vous avez à soulever un signal, écrivez à un tuyau ou utiliser signalfd () (sur linux).
  • lio_suspend () a les mêmes problèmes que select (), il ne s'adapte pas très bien au nombre de tâches.
  • lio_listio (), comme implémenté a un nombre assez limité de tâches que vous pouvez passer, et ce n'est pas trivial de trouver cette limite de manière portable. Vous devez appeler sysconf (_SC_AIO_LISTIO_MAX), ce qui peut échouer, auquel cas vous pouvez utiliser la définition AIO_LISTIO_MAX, qui ne sont pas nécessairement définies, mais vous pouvez utiliser 2, qui est défini comme la garantie d'être pris en charge.

En ce qui concerne les applications réelles utilisant posix AIO, vous pouvez jeter un oeil à lighttpd (lighty), qui a également affiché une mesure des performances lors de l'introduction du support.

La plupart des plates-formes posix prennent en charge posix AIO maintenant (Linux, BSD, Solaris, AIX, tru64). Windows le prend en charge via son fichier d'E/S superposé.ma compréhension est que seuls Solaris, Windows et Linux supporte vraiment async. fichier I / O tout le chemin jusqu'au pilote, tandis que l'autre Les systèmes d'exploitation émulent l'asynchrone. E / S avec les threads du noyau. Linux étant l'exception, son implémentation posix AIO dans glibc émule les opérations asynchrones avec des threads de niveau utilisateur, tandis que son interface d'E/S asynchrone native (io_submit() etc.) sont vraiment asynchrones jusqu'au pilote, en supposant que le pilote le supporte.

Je crois qu'il est assez courant parmi les systèmes d'exploitation de ne pas prendre en charge posix AIO pour n'importe quel fd, mais de le limiter aux fichiers réguliers.

67
répondu Arvid 2015-03-23 01:11:22

Un développeur libtorrent fournit un rapport à ce sujet: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/

10
répondu Allen 2012-11-20 04:15:36

Il est aio_write mises en œuvre dans la glibc; premier appel de la aio_read ou aio_write fonction génère un nombre d'utilisateur en mode threads, aio_write ou aio_read requêtes post de ce thread, le thread ne pread/pwrite et quand c'est fini, la réponse est affecté à l'bloqué thread appelant.

Ther est également 'réel' AIO-supporté par le niveau du noyau (besoin de libaio pour cela, voir l'appel io_submit http://linux.die.net/man/2/io_submit ); aussi besoin D'O_DIRECT pour cela (aussi peut ne pas être pris en charge par tous les systèmes de fichiers, mais les principaux le supportent)

Voir ici:

Http://lse.sourceforge.net/io/aio.html

Http://linux.die.net/man/2/io_submit

Différence entre POSIX AIO et libaio sur Linux?

2
répondu MichaelMoser 2017-05-23 12:10:30