Faire socket d'e/S de manière efficace a été résolu avec kqueue, epoll, IO ports d'achèvement et l'aime. Faire asynchrone fichier I/O est une sorte de fin de comer (à l'exception de windows overlapped I/O et solaris d'aide précoce posix AIO).
Si vous êtes à la recherche pour faire de la socket d'e/S, vous êtes probablement mieux d'utiliser un des mécanismes ci-dessus.
Le but principal de l'AIO est donc pour résoudre le problème de disque asynchrone I/O. C'est probablement pourquoi Mac OS X ne supporte AIO pour les fichiers réguliers, et pas de prises de courant (depuis kqueue n'est que tant mieux de toute façon).
Les opérations d'écriture sont généralement toujours mis en cache par le noyau et rincer à une date ultérieure. Par exemple, lorsque la tête de lecture du lecteur qui arrive à passer par l'endroit où le bloc est d'être écrite.
Toutefois, pour les opérations de lecture, si vous souhaitez que le noyau de hiérarchiser les priorités et l'ordre de votre lit, AIO est vraiment la seule option. Voici pourquoi le kernel peut (théoriquement) de le faire mieux que n'importe quel niveau de l'utilisateur de l'application:
- Le noyau voit tous les I/O disque, et pas seulement vos applications disque emplois, et pouvez les commander à l'échelle mondiale
- Le noyau (en mai), de savoir où le disque de la tête de lecture est, et peut reprendre la lecture d'emplois vous passer en ordre optimal, pour déplacer la tête de la distance la plus courte
- Le noyau peut prendre avantage de native command queuing pour optimiser vos opérations de lecture supplémentaire
- Vous pouvez être en mesure d'émettre de plus des opérations de lecture par système d'appel à l'aide de lio_listio() qu'avec readv(), surtout si votre lit ne sont pas (logiquement) contigus, l'enregistrement d'un tout petit peu de surcoût d'appels système.
- Votre programme peut être légèrement plus simple avec AIO puisque vous n'avez pas besoin d'un coup de fil à bloc dans une lecture ou d'écriture d'appel.
Cela dit, posix AIO est assez maladroit de l'interface, par exemple:
- Le seul efficace et bien supporté moyenne de rappels d'événements sont par l'intermédiaire de signaux, ce qui le rend difficile à utiliser dans une bibliothèque, puisqu'il signifie à l'aide du signal de numéros du processus du signal global de l'espace de noms. Si votre système d'exploitation ne prend pas en charge en temps réel des signaux, elle aussi signifie que vous avez à parcourir l'ensemble de vos demandes en suspens à comprendre que l'on fait terminé (c'est le cas pour Mac OS X par exemple, pas de Linux). La capture de signaux dans un environnement multi-thread fait aussi pour des problèmes de restrictions. Vous pouvez généralement pas réagir à l'événement à l'intérieur du gestionnaire de signal, mais vous avez à soulever un signal, écrire à un tuyau ou à l'utilisation signalfd() (sur linux).
- lio_suspend() a les mêmes problèmes que select (), il ne pas très bien avec le nombre d'emplois.
- lio_listio(), mis en application dispose d'assez peu de nombre d'emplois que vous pouvez passer, et il n'est pas trivial de trouver cette limite de façon portable. Vous devez appeler sysconf(_SC_AIO_LISTIO_MAX), qui peut échouer, dans ce cas vous pouvez utiliser le AIO_LISTIO_MAX définir, qui ne sont pas nécessairement définies, mais vous pouvez utiliser 2, qui est définie comme la garantie d'être pris en charge.
Comme pour les applications du monde réel à l'aide de posix AIO, vous pouvez prendre un coup d'oeil à lighttpd (lighty), qui a également posté une mesure de la performance lors de l'introduction d'un soutien.
La plupart des plateformes posix prend en charge la norme posix AIO (Linux, BSD, Solaris, AIX, tru64). Windows prend en charge via son superposées fichier I/O. Ma compréhension est que seulement Solaris, Windows et Linux supporte vraiment asynchrone. fichier I/O tout le chemin vers le pilote, tandis que les autres Systèmes d'exploitation émuler la async. I/O avec les threads du noyau. Linux étant l'exception, son posix AIO mise en œuvre dans la glibc, émule des opérations asynchrones avec des threads de niveau utilisateur, alors que son natif async interface I/O (io_submit (), etc.) sont vraiment asynchrone tout le chemin vers le pilote, en supposant que le pilote prend en charge.
Je crois que c'est assez commun parmi les Systèmes d'exploitation ne prennent pas en charge la norme posix AIO pour tout fd, mais de le restreindre à des fichiers normaux.