linux - ¿Cuál es el estado de la E/S asíncrona POSIX(AIO)?
asynchronous bsd (4)
Hay páginas diseminadas por la web que describen las instalaciones POSIX AIO en cantidades variables de detalles. Ninguno de ellos es terriblemente reciente. No está claro qué, exactamente, están describiendo. Por ejemplo, el sitio web "oficial" (?) Para el soporte de E / S asíncronas del kernel de Linux dice que los sockets no funcionan, pero las páginas del manual "aio.h" en mi estación de trabajo Ubuntu 8.04.1 parecen implicar que funciona para descriptores de archivos arbitrarios. Luego hay otro proyecto que parece funcionar en la capa de la biblioteca con incluso menos documentación.
Me gustaría saber:
- ¿Cuál es el propósito de POSIX AIO? Dado que el ejemplo más obvio de una implementación que puedo encontrar dice que no admite sockets, todo me parece extraño. ¿Es solo para E / S de disco asíncrono? Si es así, ¿por qué la API hiper general? Si no, ¿por qué la E / S de disco es lo primero que se atacó?
- ¿Dónde hay ejemplos completos de programas POSIX AIO que puedo ver?
- ¿Alguien realmente lo usa, de verdad?
- ¿Qué plataformas son compatibles con POSIX AIO? ¿Qué partes de él apoyan? ¿Alguien realmente apoya la implícita "Cualquier E / S a cualquier FD" que
<aio.h>
parece prometer?
Los otros mecanismos de multiplexación disponibles para mí son perfectamente buenos, pero los fragmentos aleatorios de información que circulan por ahí me han causado curiosidad.
Hacer las E / S de socket de manera eficiente se ha resuelto con los puertos de terminación kqueue, epoll, IO y "me gusta". Hacer E / S de archivos asíncronos es una especie de punto de retraso (aparte de la E / S solapada de Windows y el soporte temprano de Solaris para POSIO AIO).
Si está buscando hacer E / S de socket, probablemente sea mejor que use uno de los mecanismos anteriores.
El objetivo principal de AIO es, por tanto, resolver el problema de la E / S de disco asíncrona. Es muy probable que Mac OS X solo admita AIO para archivos regulares, y no para sockets (ya que de todos modos kqueue lo hace mucho mejor).
Las operaciones de escritura generalmente son almacenadas en memoria caché por el kernel y descartadas en un momento posterior. Por ejemplo, cuando el cabezal de lectura de la unidad pasa por la ubicación donde se escribirá el bloque.
Sin embargo, para operaciones de lectura, si desea que el kernel priorice y ordene sus lecturas, AIO es realmente la única opción. He aquí por qué el kernal puede (teóricamente) hacerlo mejor que cualquier aplicación de nivel de usuario:
- El kernel ve todas las E / S de disco, no solo sus trabajos de disco de aplicaciones, y puede ordenarlos a nivel global
- El kernel (puede) saber dónde está el cabezal de lectura del disco, y puede elegir los trabajos de lectura que le pasa en el orden óptimo, para mover el cabezal la distancia más corta
- El núcleo puede aprovechar las colas de comandos nativos para optimizar aún más sus operaciones de lectura
- Es posible que pueda emitir más operaciones de lectura por llamada del sistema usando lio_listio () que con readv (), especialmente si sus lecturas no son (lógicamente) contiguas, lo que ahorra un poco de sobrecarga de llamadas al sistema.
- Su programa puede ser un poco más simple con AIO ya que no necesita un hilo adicional para bloquear en una llamada de lectura o escritura.
Dicho esto, posix AIO tiene una interfaz bastante incómoda, por ejemplo:
- La única forma eficiente y bien soportada de devolución de llamadas de eventos es a través de señales, lo que hace que sea difícil de usar en una biblioteca, ya que significa el uso de números de señal del espacio de nombres de la señal global del proceso. Si su sistema operativo no admite señales en tiempo real, también significa que debe recorrer todas sus solicitudes pendientes para averiguar cuál terminó realmente (este es el caso de Mac OS X, por ejemplo, no de Linux). La captura de señales en un entorno de subprocesos múltiples también genera algunas restricciones difíciles. Por lo general, no puede reaccionar al evento dentro del controlador de señal, pero debe elevar una señal, escribir en un conducto o usar signalfd () (en Linux).
- lio_suspend () tiene los mismos problemas que select (), no se escala muy bien con la cantidad de trabajos.
- lio_listio (), implementado tiene un número bastante limitado de trabajos que puede pasar, y no es trivial encontrar este límite de manera portátil. Debe llamar a sysconf (_SC_AIO_LISTIO_MAX), que puede fallar, en cuyo caso puede usar la definición AIO_LISTIO_MAX, que no está necesariamente definida, pero luego puede usar 2, que se define como garantizado para ser compatible.
En cuanto a la aplicación en el mundo real utilizando posix AIO, podría echar un vistazo a lighttpd (lighty), que también publicó una medición de rendimiento al presentar soporte.
La mayoría de las plataformas posix son compatibles ahora con AIO posix (Linux, BSD, Solaris, AIX, tru64). Windows lo admite a través de su E / S de archivo superpuesto. Tengo entendido que solo Solaris, Windows y Linux realmente admiten asincrónicos. archivo de E / S hasta el controlador, mientras que los otros sistemas operativos emulan la asincrónica. E / S con hilos del kernel. Linux es la excepción, su implementación POSIO AIO en glibc emula operaciones asincrónicas con subprocesos de nivel de usuario, mientras que su interfaz de E / S asincrónica nativa (io_submit () etc.) es verdaderamente asíncrona hasta el controlador, suponiendo que el controlador lo soporte .
Creo que es bastante común entre los sistemas operativos no admitir POSIX AIO para cualquier fd, pero restringirlo a archivos regulares.
Hay aio_write - implementado en glibc; La primera llamada de la función aio_read o aio_write genera un número de subprocesos de modo de usuario, aio_write o aio_read solicitudes de publicación a esa cadena, la secuencia preed / pwrite y, cuando finaliza, la respuesta se publica nuevamente en la cadena de llamadas bloqueada.
También es "real" aio - soportado por el nivel kernel (necesita libaio para eso, vea la llamada io_submit http://linux.die.net/man/2/io_submit ); también necesita O_DIRECT para eso (también puede no ser compatible con todos los sistemas de archivos, pero los principales sí lo admiten)
mira aquí:
http://lse.sourceforge.net/io/aio.html
La E / S de red no es una prioridad para AIO porque todos los que escriben servidores de red POSIX usan un enfoque basado en eventos, no bloqueante. El antiguo enfoque de Java "miles de millones de hilos de bloqueo" apesta horriblemente.
La E / S de escritura de disco ya está almacenada en el búfer y la E / S de lectura de disco se puede recuperar previamente en el búfer usando funciones como posix_fadvise. Eso deja la E / S de disco directa y sin búfer como el único propósito útil para AIO.
La E / S directa y sin búfer solo es realmente útil para las bases de datos transaccionales, y esas tienden a escribir sus propios hilos o procesos para administrar sus E / S de disco.
Por lo tanto, al final eso deja POSIX AIO en la posición de no servir a ningún propósito útil. No lo uses
Un desarrollador libtorrent proporciona un informe sobre esto: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/