2

板子介绍:

我正在开发一块板上装有 ST40 芯片的板,它基本上用于捕获 DVB 流并将其显示在电视上。该板在 Linux 操作系统上运行。

问题描述:

我正在尝试使用 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 板上出现故障的原因是什么?

4

3 回答 3

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

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

于 2012-08-04T14:16:22.157 回答
2

从手册页引用:

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

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

你的subblk块对齐了吗?两个系统是否具有相同的文件系统和/或内核版本?

于 2012-05-09T09:31:42.920 回答
1

O_DIRECT 标志在内部使用 DMA,在我的内核中,未启用 DMA。这就是它在我的台式电脑上工作但在主板上不起作用的基本原因。他们有不同的内核,一个启用了 DMA,另一个没有启用 DMA。

于 2012-05-09T11:21:02.343 回答