stringtranslate.com

empalme (llamada al sistema)

splice() es una llamada al sistema específica de Linux que mueve datos entre un descriptor de archivo y una tubería sin un viaje de ida y vuelta al espacio del usuario. La llamada al sistema relacionada vmsplice() mueve o copia datos entre una tubería y el espacio del usuario. Idealmente, splice y vmsplice funcionan reasignando páginas y en realidad no copian ningún dato, lo que puede mejorar el rendimiento de E/S . Como las direcciones lineales no necesariamente corresponden a direcciones físicas contiguas, esto puede no ser posible en todos los casos y en todas las combinaciones de hardware.

Funcionamiento

Con splice() , uno puede mover datos de un descriptor de archivo a otro sin incurrir en ninguna copia del espacio del usuario al espacio del kernel, lo que generalmente se requiere para reforzar la seguridad del sistema y también para mantener una interfaz simple para que los procesos lean y escriban en archivos. splice() funciona utilizando el buffer de tubería . Un buffer de tubería es un buffer de memoria en el kernel que es opaco para el proceso del espacio de usuario. Un proceso de usuario puede empalmar el contenido de un archivo de origen en este buffer de tubería, luego empalmar el buffer de tubería en el archivo de destino, todo sin mover ningún dato a través del espacio de usuario.

Orígenes

Linus Torvalds describió splice() en un correo electrónico de 2006, que se incluyó en un artículo de KernelTrap . [1]

La implementación del splice de Linux toma prestadas algunas ideas de una propuesta original de Larry McVoy en 1998. [2] Las llamadas al sistema de splice aparecieron por primera vez en la versión 2.6.17 del kernel de Linux [1] y fueron escritas por Jens Axboe .

Prototipo

 ssize_t empalme ( int fd_in , loff_t * off_in , int fd_out , loff_t * off_out , size_t len ​​, unsigned int flags );             

Algunas constantes que son de interés son:

/* Banderas de empalme (aún no establecidas en piedra). */ #ifndef SPLICE_F_MOVE #define SPLICE_F_MOVE 0x01 #endif #ifndef SPLICE_F_NONBLOCK #define SPLICE_F_NONBLOCK 0x02 #endif #ifndef SPLICE_F_MORE #define SPLICE_F_MORE 0x04 #endif #ifndef SPLICE_F_GIFT #define SPLICE_F_GIFT 0x08 #endif

Ejemplo

Este es un ejemplo de empalme en acción:

/* Transferencia desde el disco a un registro. */ int log_blocks ( struct log_handle * handle , int fd , loff_t offset , size_t size ) { int filedes [ 2 ]; int ret ; size_t to_write = size ; ret = pipe ( filedes ); if ( ret < 0 ) goto out ; /* empalmar el archivo en la tubería (datos en la memoria del núcleo). */ while ( to_write > 0 ) { ret = splice ( fd , & offset , filedes [ 1 ], NULL , to_write , SPLICE_F_MORE | SPLICE_F_MOVE ); if ( ret < 0 ) goto pipe ; else to_write -= ret ; } to_write = size ; /* empalmar los datos en la tubería (en la memoria del núcleo) en el archivo. */ mientras ( para_escribir > 0 ) { ret = splice ( files [ 0 ], NULL , manejador -> fd , & ( manejador -> fd_offset ), para_escribir , SPLICE_F_MORE | SPLICE_F_MOVE ); si ( ret < 0 ) ir a la tubería ; de lo contrario para_escribir -= ret ; }                                                                                           tubería : cerrar ( archivos [ 0 ]); cerrar ( archivos [ 1 ]); salida : si ( ret < 0 ) retorna - errno ; retorna 0 ; }              

Llamadas complementarias al sistema

splice() es una de las tres llamadas del sistema que completan la arquitectura de splice() . vmsplice() puede mapear un área de datos de la aplicación en una tubería (o viceversa), permitiendo así transferencias entre tuberías y memoria de usuario, mientras que sys_splice() realiza transferencias entre un descriptor de archivo y una tubería. tee() es la última parte de la trilogía. Duplica una tubería en otra, lo que permite bifurcaciones en la forma en que las aplicaciones se conectan con tuberías.

Requisitos

Al utilizar splice() con sockets, el controlador de red (NIC) debe ser compatible con DMA; de lo contrario, splice() no ofrecerá una mejora significativa en el rendimiento. La razón de esto es que cada página de la tubería se llenará hasta el tamaño del marco (1460 bytes de los 4096 bytes disponibles por página). splice() no es compatible con sockets UDP.

No todos los tipos de sistemas de archivos admiten splice() . Además, los sockets AF_UNIX no admiten splice() .

Véase también

Referencias

  1. ^ ab "Linux: Explicación de splice() y tee()". kerneltrap.org. 2006-04-21. Archivado desde el original el 2013-05-21 . Consultado el 2014-04-27 .
  2. ^ "Copia archivada". Archivado desde el original el 4 de marzo de 2016. Consultado el 28 de febrero de 2016 .{{cite web}}: CS1 maint: archived copy as title (link)

Enlaces externos