2009-08-02 18 views
6

De acuerdo con la documentación sobre aio_read/write, hay básicamente 2 formas en que la biblioteca AIO puede informar a su aplicación que se ha completado una operación de E/S de archivo asíncrono. Ya sea 1) puede usar una señal, 2) puede usar una función de devolución de llamadaBiblioteca POSIX AIO y controladores de devolución de llamada

Creo que las funciones de devolución de llamada son bastante preferibles a las señales, y probablemente sean mucho más fáciles de integrar en bibliotecas de subprocesos múltiples de alto nivel. Lamentablemente, la documentación para esta funcionalidad es un desastre, por decir lo menos. Algunas fuentes, como man page for the sigevent struct, indican que debe establecer el miembro de datos sigev_notify en la estructura sigevent en SIGEV_CALLBACK y luego proporcionar un controlador de funciones. Presumiblemente, el controlador se invoca en el mismo hilo. Otro documentation indica que debe establecer sigev_notify a SIGEV_THREAD, que invocará el controlador de devolución de llamada en un subproceso recién creado.

En cualquier caso, en mi sistema Linux (Ubuntu con un kernel 2.6.28) SIGEV_CALLBACK no parece estar definido en ninguna parte, pero SIGEV_THREAD funciona como se anuncia. Desafortunadamente, crear un nuevo hilo para invocar el controlador de devolución de llamada parece ser realmente ineficiente, especialmente si necesita invocar a muchos controladores. Sería mejor utilizar un conjunto de hilos existente, similar a la forma en que funcionan la mayoría de los demultiplexores de eventos de E/S de red. Algunas versiones de UNIX, como QNX, incluyen un indicador SIGEV_SIGNAL_THREAD, que le permite invocar manejadores usando un hilo específico especificado, pero esto no parece estar disponible en Linux, ni siquiera parece ser parte del POSIX estándar.

Entonces, ¿es posible usar la biblioteca AIX de POSIX de una manera que invoca manejadores de usuario en un hilo/subproceso de fondo preasignado, en lugar de crear/destruir un nuevo subproceso cada vez que se invoca un controlador?

Respuesta

1

Un enfoque es usar un SIGEV_SIGNAL con un realtime signal para "llevar" el descriptor de archivo preparado a un manejador de señal. señales en tiempo real de la cola y de la señal controladores ejecutan de forma asíncrona en un hilo, por lo que este enfoque es más o menos funcionalmente equivalente a SIGEV_CALLBACK:

/* 
* Warning! Untested! 
* Also, safe initialization, per-thread signal masking and 
* error-checking omitted. 
*/ 

static void my_callback(int sig, siginfo_t *info, void *context) { 
    int fd; 

    fd = info->si_value.sival_int; 
    /* ...enqueue the fd for processing... */ 
} 

struct sigaction sa; 

sa.sa_handler = my_callback;     /* Register our async callback */ 
sa.sa_flags = SA_SIGINFO; 
sigaction(SIGRTMIN+1, &sa, NULL); 
... 

struct aiocb ac; 

ac.aio_filedes = some_fd; 
ac.aio_sigevent.sigev_notify = SIGEV_SIGNAL; 
ac.aio_sigevent.sigev_signo = SIGRTMIN+1; /* Associate callback w. aiocb */ 
.... 
aio_read(&ac); 

Ahora su my_callback se activar de forma asíncrona en un hilo, y le toca a usted para pasar el fd a tu hilo de ayuda. Consulte también this bit of SGI code, que muestra cómo retroceder a SIGEV_SIGNAL cuando SIGEV_CALLBACK no está disponible.

+2

el problema con las señales es que si usted es una biblioteca, está configurando los manejadores en el contexto de su usuario. Lo cual puede sorprender y molestar a algunos de los usuarios. –

+0

De hecho, esto es muy malo.Las bibliotecas nunca deben tocar señales, excepto para enmascararlas temporalmente. –

2

Normalmente me resulta más simple y más portátil para simular IO asíncrona haciendo IO ordinario en un subproceso o subprocesos de fondo dedicados, enviando devoluciones de llamadas de terminación de la manera que me gusta.

0

Si le preocupan que se creen/destruyan varios subprocesos para cada llamada de finalización, ¿por qué no lote sus IO?

lista utilización io apis ..

struct aiocb **myaiocb; 
[just an array of aiocb pointers, where each aiocb points to an IO buffer 
    and the operation to be performed, etc] 
.... 
lio_listio(LIO_NOWAIT, myaiocb, num_ios, &sigevent); 

La ventaja con la lista IO es que el manejador de devolución de llamada sólo después de que todos los IOs en la lista completa (con éxito/sin éxito). Puede verificar el estado de cada operación IO usando aio_return.

0

Este es un hilo muy viejo, pero apareció en la parte superior de Google cuando se busca este mismo problema. Ahora hay una extensión de GNU aio_init que le permite especificar la cantidad máxima de hilos que debería usar y la duración de esos hilos.

Cuestiones relacionadas