tabla - Linux Zero-Copy: transfiere páginas de memoria entre dos procesos con vmsplice
ejercicios sobre gestión de memoria sistemas de operación (1)
Actualmente, estoy tratando de entender el valor de splice / vmsplice. Con respecto al caso de uso de IPC, me topé con la siguiente respuesta en stackoverflow: https://stackoverflow.com/a/1350550/1305501
Pregunta: ¿Cómo transferir páginas de memoria de un proceso a otro usando vmsplice sin copiar datos (es decir, copiar en cero)?
La respuesta mencionada anteriormente afirma que es posible. Sin embargo, no contiene ningún código fuente. Si entiendo la documentación de vmsplice
correctamente, la siguiente función transferirá las páginas de la memoria a una tubería (búfer del kernel) sin copiar, si la memoria está correctamente asignada y alineada. Manejo de errores omitido por la facilidad de presentación.
// data is aligned to page boundaries,
// and length is a multiple of the page size
void transfer_to_pipe(int pipe_out, char* data, size_t length)
{
size_t offset = 0;
while (offset < length) {
struct iovec iov { data + offset, length - offset };
offset += vmsplice(pipe_out, &iov, 1, SPLICE_F_GIFT);
}
}
Pero, ¿cómo se puede acceder a las páginas de memoria desde el espacio del usuario sin copiarlas? Aparentemente los siguientes métodos no funcionan:
-
vmsplice
: esta función también se puede utilizar para la dirección inversa. Pero de acuerdo con los comentarios en las fuentes del kernel , los datos serán copiados. -
read
: Puedo imaginar que esta función hace algo de magia si la memoria está correctamente alineada, pero lo dudo. -
mmap
: no es posible en tubo. Pero, ¿existe algún tipo de archivo virtual que se pueda usar en su lugar, es decir,splice
las páginas de memoria al archivo virtual y colocarlo en unmmap
? - ...?
¿No es posible en absoluto con vmsplice
?
Como mencionó R .., solo necesitas pasar el fd al proceso de recepción de somehow y en el otro lado usarlo como un fd normal.
edición: en realidad, debe usar vmsplice () en el lado de envío para asignar el búfer al tubo y empalme () en el lado de recepción en el otro extremo del tubo. Vea un ejemplo here .
Otra opción sería utilizar un mmap-ing compartido.