plantillas - La bandera O_DIRECT no funciona
plantillas divi (3)
El indicador O_DIRECT usa DMA internamente y en mi kernel, DMA no está habilitado. Esta es la razón básica por la que funcionaba en mi PC de escritorio pero no funcionaba en la Junta. Tenían diferentes núcleos en ellos, uno en el que DMA estaba habilitado y otro en el que DMA no estaba habilitado.
Introducción a la Junta:
Estoy trabajando en una placa que tiene un chip ST40 básicamente utilizado para capturar el flujo de DVB y mostrarlo en el televisor. La placa se ejecuta en el sistema operativo Linux.
Descripción del problema:
Estoy tratando de leer datos de un archivo grande (aproximadamente 2 GB) en USB usando el indicador O_DIRECT. Aquí está el fragmento de código relevante:
char subblk[BLKSIZE];
open (filename2,O_CREAT|O_WRONLY|O_DIRECT,S_IRWXU|S_IRWXG|S_IRWXO);
read (fp,subblk,BLKSIZE);
Dice que la lectura falló con el error número 22 - "EINVAL 22 /* Invalid argument"
Para aclarar si se trataba de un problema de programación o de algún problema dependiente de la arquitectura, ejecuté el mismo código en mi sistema de escritorio, funcionó perfectamente bien y pude imprimir los caracteres que acabo de leer. ¿Cuál es la razón por la que está fallando en mi placa ST40?
Para citar de la página del manual:
El indicador O_DIRECT puede imponer restricciones de alineación en la longitud y dirección de los almacenamientos intermedios de espacio de usuario y el desplazamiento de archivo de E / S. En Linux, las restricciones de alineación varían según el sistema de archivos y la versión del kernel, y pueden estar ausentes por completo. Sin embargo, actualmente no existe una interfaz independiente del sistema de archivos para que una aplicación descubra estas restricciones para un archivo o sistema de archivos determinado. Algunos sistemas de archivos proporcionan sus propias interfaces para hacerlo, por ejemplo, la operación XFS_IOC_DIOINFO en xfsctl (3).
En Linux 2.4, los tamaños de transferencia y la alineación del búfer de usuario y el desplazamiento de archivos deben ser múltiplos del tamaño de bloque lógico del sistema de archivos. Bajo Linux 2.6, la alineación con los límites de 512 bytes es suficiente.
¿Está tu bloque subblk
bien alineado? ¿Ambos sistemas tienen el mismo sistema de archivos y / o la versión del kernel?
Debe alinear el búfer por el límite del bloque del sistema de archivos. Para lograr esto, no deberías usar buffer en la pila (como en tu ejemplo), ni llamar a malloc(BLKSIZE)
, pero deberías usar memalign (). Entonces tu código será:
/* make sure BLKSIZE is defined as 512 */
char *subblk = memalign(BLKSIZE, BLKSIZE);
open (filename2,O_CREAT|O_WRONLY|O_DIRECT,S_IRWXU|S_IRWXG|S_IRWXO);
read (fp,subblk,BLKSIZE);
Por qué su código está funcionando en el escritorio es probablemente la alineación accidental o el tipo de sistema de archivos diferente (sin requisito de alineación).