`splice()` es una llamada al sistema específica de Linux que transfiere datos entre un descriptor de archivo y una tubería sin necesidad de acceder al espacio de usuario. La llamada al sistema relacionada, `vmsplice()` , transfiere o copia datos entre una tubería y el espacio de usuario. Idealmente, `splice` y `vmsplice` funcionan reasignando páginas y no copian datos, lo que puede mejorar el rendimiento de E/S . Dado que las direcciones lineales no siempre corresponden a direcciones físicas contiguas, esto podría no ser posible en todos los casos ni en todas las combinaciones de hardware.
Funcionamiento
Con `splice()` , se pueden transferir datos de un descriptor de archivo a otro sin realizar copias del espacio de usuario al espacio del kernel, lo cual suele ser necesario para garantizar la seguridad del sistema y mantener una interfaz sencilla para que los procesos lean y escriban archivos. `splice()` funciona mediante el uso del búfer de tubería . Un búfer de tubería es un búfer de memoria dentro del kernel que es opaco para el proceso de espacio de usuario. Un proceso de usuario puede copiar el contenido de un archivo de origen en este búfer de tubería y luego copiar el contenido del búfer de tubería en el archivo de destino, todo ello sin transferir datos 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 de splice de Linux toma prestadas algunas ideas de una propuesta original de Larry McVoy en 1998. [ 2 ] Las llamadas al sistema 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 splice ( int fd_in , loff_t * off_in , int fd_out , loff_t * off_out , size_t len , unsigned int flags );Algunas constantes de interés son:
// Indicadores de empalme (aún no definidos). #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 #endifEjemplo
Este es un ejemplo de empalme en acción:
// Transferencia del disco a un registro. int log_blocks ( struct log_handle * handle , int fd , loff_t offset , size_t size ) { int file_descriptions [ 2 ]; size_t to_write = size ; int ret = pipe ( file_descriptions ); if ( ret < 0 ) { goto out ; } // Empalmar el archivo en la tubería (datos en la memoria del kernel). while ( to_write > 0 ) { ret = splice ( fd , & offset , file_descriptions [ 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 kernel) en el archivo. while ( to_write > 0 ) { ret = splice ( file_descriptions [ 0 ], NULL , handle -> fd , & ( handle -> fd_offset ), to_write , SPLICE_F_MORE | SPLICE_F_MOVE ); if ( ret < 0 ) { goto pipe ; } else { to_write -= ret ; } }tubería : cerrar ( file_descriptions [ 0 ]); cerrar ( file_descriptions [ 1 ] ); salida : devolver ret < 0 ? -errno : 0 ; }Llamadas al sistema complementarias
splice() es una de las tres llamadas al sistema que completan la arquitectura de splice() . vmsplice() puede mapear un área de datos de la aplicación en una tubería (o viceversa), lo que permite transferencias entre tuberías y memoria de usuario, mientras que sys_splice() transfiere 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 usar 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. Esto se debe a que cada página del canal se llenará hasta alcanzar el tamaño de trama (1460 bytes de los 4096 bytes disponibles por página).
No todos los tipos de sistemas de archivos admiten la función splice() .
Véase también
Referencias
- 1 2 "Linux: Explicando splice() y tee()" . kerneltrap.org. 21 de abril de 2006. Archivado del original el 21 de mayo de 2013. Consultado el 27 de abril de 2014 .
- ↑ "Copia archivada" . Archivado del original el 4 de marzo de 2016. Consultado el 28 de febrero de 2016 .
{{cite web}}: CS1 mantenimiento: copia archivada como título ( enlace )
Enlaces externos
- Núcleo de Linux 2.6.17 (kernelnewbies.org)
- Dos nuevas llamadas al sistema: splice() y sync_file_range() ( LWN.net )
- Algunas nuevas llamadas al sistema (LWN.net)
- Características del kernel de Linux
- llamadas al sistema