从具有 O_DIRECT 的 HDD 读取()失败并显示 22(EINVAL,无效参数)

sam*_*rai 3 linux io hard-drive block-device

我想read()用 SATA HDD制作一个基本的/dev/sdd。Awrite()似乎有效。也read()可以write()在没有 Flag 的情况下工作O_DIRECT。我读过,它必须与块大小对齐。所以我用它来获取块大小:

root$ blockdev --getsize /dev/sdd
488397168

root$ blockdev --getsize64 /dev/sdd
250059350016

root$ python -c "print 250059350016.0/488397168"
512.0
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我有根。HDD 通过 PCIe SATA 卡连接,并向lspci -vv我显示它使用基本的 ahci ( drivers/ata/ahci.c) 驱动程序。我在 64 位 Power Architecture 上使用 3.2.0 Linux 内核。

这是我的代码:

root$ blockdev --getsize /dev/sdd
488397168

root$ blockdev --getsize64 /dev/sdd
250059350016

root$ python -c "print 250059350016.0/488397168"
512.0
Run Code Online (Sandbox Code Playgroud)

输出是:

tmp_buffer is at: 1cc80010 % 512 = 16
buffer is at: 1cc80200 % 512 = 0
try to read and then dump buffer:
Error: Invalid argument
Run Code Online (Sandbox Code Playgroud)

编辑:我已经按照布雷特·黑尔的答案的建议更新了我的来源。不幸的是我仍然收到错误。我找出块大小的方法可以吗?我的对齐方式正确吗?

非常感谢您的阅读,
法比安

Bre*_*ale 5

直接 DMA 传输通常需要对齐缓冲区。从man

O_DIRECT 标志可以对用户空间缓冲区的长度和地址以及 I/O 的文件偏移施加对齐限制。...在 Linux 2.6 下,对齐 512 字节边界就足够了。

因此char buffer[512];可能需要与 512 字节地址对齐。

可能无法在堆栈上实现这种对齐,因此:

static char buffer[512] __attribute__ ((__aligned__ (512)));

可能有效。或者也许这种对齐方式将在堆栈上起作用。或者,如果您使用的是 x86,则可以使用<mm_malloc.h>内部支持函数:_mm_malloc_mm_free