O_DIRECT标志无效

时间:2012-05-09 09:07:14

标签: c linux io

董事会简介:

我正在制作一块板上有ST40芯片,主要用于捕捉DVB流并在电视上显示。该板在Linux OS上运行。

问题描述:

我正在尝试使用O_DIRECT标志从USB上的大文件(大约2 GB)读取数据。 以下是相关的代码段:

char subblk[BLKSIZE];
open (filename2,O_CREAT|O_WRONLY|O_DIRECT,S_IRWXU|S_IRWXG|S_IRWXO);
read (fp,subblk,BLKSIZE);

它表示读取失败,错误编号为22 - "EINVAL 22 /* Invalid argument"

为了澄清这是一个编程问题还是一些与架构有关的问题,我在我的桌面系统上运行了相同的代码,它工作得非常好,我能够打印我刚读过的字符。我的ST40主板出现故障的原因是什么?

3 个答案:

答案 0 :(得分:10)

您应该按文件系统块边界对齐缓冲区。要实现这一点,不应在堆栈上使用缓冲区(如示例中所示),也不要调用malloc(BLKSIZE),但应使用memalign()。所以你的代码将是:

/* 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);

为什么您的代码在桌面上工作可能是意外对齐不同的文件系统类型(没有对齐要求)。

答案 1 :(得分:2)

引用手册页:

  

O_DIRECT标志可能会对长度和长度施加对齐限制   用户空间缓冲区的地址和I / O的文件偏移量。在Linux中   对齐限制因文件系统和内核版本而异   可能完全没有。但是目前没有文件   系统无关的接口,供应用程序发现这些   对给定文件或文件系统的限制。一些文件系统   提供他们自己的接口,例如   xfsctl(3)中的XFS_IOC_DIOINFO操作。

     

在Linux 2.4下,传输大小和用户缓冲区的对齐方式   并且文件偏移量必须都是逻辑块大小的倍数   文件系统。在Linux 2.6下,对齐到512字节边界   就足够了。

您的subblk区块是否排列良好?两个系统是否具有相同的文件系统和/或内核版本?

答案 2 :(得分:1)

O_DIRECT标志在内部使用DMA,在我的内核中,DMA未启用。这就是为什么它在我的桌面电脑上工作但在电路板上没有功能的基本原因..它们有不同的内核,其中一个启用了DMA,另一个启用了DMA ...