linux sockets asynchronous

Zócalos de Linux eficientes(DMA/copia cero)



sockets asynchronous (2)

AFAIK está utilizando las llamadas más eficientes disponibles si no puede usar sendfile (2). El problema C10K cubre varios aspectos del código de red de alto rendimiento eficiente.

Estoy construyendo un servidor Linux de muy alto rendimiento (basado en epoll, sockets no bloqueantes y disco asíncrono IO [basado en io_submit / io_getevents / eventfd]). Algunos de mis puntos de referencia muestran que la forma en que manejo los enchufes no es lo suficientemente eficiente para mis requerimientos. En particular, me preocupa obtener datos del búfer de espacio de usuario a la tarjeta de red, y de la tarjeta de red al búfer de espacio de usuario (ignoremos la llamada de archivo send por ahora).

Por lo que entiendo, llamar a lectura / escritura en un socket Linux no bloqueante no es totalmente asincrónico: la llamada al sistema bloquea mientras copia el buffer desde el espacio de usuario al kernel (o al revés), y solo luego regresa. ¿Hay alguna manera de evitar esto escuchado en Linux? En particular, ¿hay una llamada de escritura totalmente asíncrona que puedo hacer en un socket que devolvería inmediatamente, DMA el búfer de espacio de usuario a la tarjeta de red, según sea necesario, y señalizar / establecer un evento / etc. ¿en la terminación? Sé que Windows tiene una interfaz para esto, pero no pude encontrar nada sobre esto en Linux.

¡Gracias!


Recientemente, se ha hablado sobre Linux-Kernel acerca de proporcionar una API para algo similar, pero el problema es que no se puede DMA desde los búferes del espacio de usuario general a la tarjeta de red, porque:

  • Lo que parece datos contiguos en el espacio de direcciones lineales del espacio de usuario probablemente no sea contiguo en la memoria física, lo que es un problema si la tarjeta de red no hace DMA dispersa;
  • En muchas máquinas, no todas las direcciones de memoria física son "DMA-able". No hay forma en este momento para que una aplicación de espacio de usuario solicite específicamente un búfer con capacidad DMA.

En núcleos recientes, puede intentar usar vmsplice y splice para lograr lo que desea: vmsplice las páginas (con SPLICE_F_GIFT ) que desea enviar a una tubería, luego SPLICE_F_MOVE (con SPLICE_F_MOVE ) de la tubería en el zócalo.