2008-09-17 9 views
84

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 "oficial" (?) web site for Linux kernel asynchronous I/O support here 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 está another project that seems to work at the library layer con incluso menos documentación.¿Cuál es el estado de la E/S asíncrona POSIX (AIO)?

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 está el ejemplo completo 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.

Respuesta

24

Las E/S de red no son 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 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 que deja POSIX AIO en la posición de no servir cualquier útil. No lo uses

+7

Lo sobre leer/escribir desde sistemas de archivos de red (NFS, Samba)? –

+1

bien. Tengo varios escritores tontos grandes que, si los dejo ir al caché, golpearán dirty_ratio en picos, bloqueando a todos los demás. Si solo uso IO directo en ellos, es demasiado lento. Si tuviera solo 1 hilo, podría hacerlo solo, pero será difícil soportar diferentes prioridades IO en 1 banda de rodadura. AIO + CFQ realmente parece una buena combinación, si AIO trabajó –

+29

No estoy de acuerdo. La E/S de disco tiende a almacenarse en el búfer pero puede estar bloqueando. Al sondear un archivo FD, siempre informa que el FD es legible, incluso cuando se bloqueará. Esto hace que sea imposible realizar operaciones sin bloqueo en los archivos del disco de una manera eficaz, a menos que uno use hilos o AIO. – Hongli

61

Hacer las conexiones de E/S de manera eficiente ha sido resuelto con kqueue, epoll, puertos de terminación 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 utilice 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 se guardan en la memoria caché por el kernel y se eliminan 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 meollo puede hacer (en teoría) que mejor que cualquier aplicación de nivel de usuario:

  • que ve el núcleo de todos los discos S, no sólo sus empleos disco, I/aplicaciones, y pueden hacer pedidos a nivel mundial
  • El kernel (puede) saber dónde está el cabezal de lectura del disco, y puede elegir los trabajos de lectura que le pasa en orden óptimo, para mover el cabezal la distancia más corta
  • El kernel puede aprovechar native command queuing para optimizar sus operaciones de lectura más
  • Es posible que pueda emitir más operaciones de lectura por llamada al sistema utilizando lio_listio() que con readv(), especialmente si y nuestras 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, AIO posix tiene una interfaz bastante incómodo, por ejemplo:

  • La única eficiente y bien soportado media de devoluciones de llamada de eventos son a través de señales, que hace que sea difícil de usar en una biblioteca, ya que significa usar 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 el número 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 forma 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 AIO POSIX, que podría echar un vistazo a lighttpd (lighty), que también registró una performance measurement cuando la introducción de apoyo.

La mayoría de las plataformas POSIX ahora admiten 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 los archivos normales.

+0

Windows ha tenido OVERLAPPED I/O archivos de disco de soporte desde que Win32 salió por primera vez. No es nada nuevo. Y en POSIX, el espacio de nombres de la señal no es global de proceso, es por subproceso. Las señales se envían a hilos específicos (¿o es una excepción a eso, no se recuerda con certeza?). –

+1

No hay forma de especificar a qué subproceso AIO entrega sus señales. En Linux, parece * en su mayoría * entregarlo al hilo que emitió el comando aio _ *(), pero no siempre (la única solución que he encontrado para esto fue crear múltiples señales). Hubo un parche de Linux en la lista de correo del núcleo hace unos años que agregaría esto, pero nunca lo hizo, y hubiera sido una extensión de POSIX. En Mac OS X, las señales parecen ser principalmente entregadas al hilo principal (en mi experiencia). No creo que POSIX requiera un comportamiento específico, si lo hace, me encantaría ver la parte de la especificación. – Arvid

+4

La implementación de glibc de aio_read/write usa subprocesos en el dominio de usuario, por lo que ni siquiera los hilos del kernel se usan aquí. – Marenz

2

No es 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.

Ther también es 'real' aio - compatible con el nivel kernel (necesita libaio para eso, vea la llamada io_submit http://linux.die.net/man/2/io_submit); También es necesario O_DIRECT para eso (también pueden no ser compatibles con todos los sistemas de archivos, pero los más importantes son compatibles con este)

ver aquí:

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

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

Difference between POSIX AIO and libaio on Linux?

+0

Muchas de las deficiencias de 'aio_write' están cubiertas anteriormente, en https://stackoverflow.com/a/5307557/13564 – Glyph

Cuestiones relacionadas