gpt4 book ai didi

linux - 使用 O_DIRECT 从 HDD 读取()失败并显示 22(EINVAL,无效参数)

转载 作者:太空狗 更新时间:2023-10-29 11:46:28 25 4
gpt4 key购买 nike

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

root$ blockdev --getsize /dev/sdd
488397168

root$ blockdev --getsize64 /dev/sdd
250059350016

root$ python -c "print 250059350016.0/488397168"
512.0

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

这是我的代码:

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main() {

int r;
char *buffer, *tmp_buffer;
// alloc more than necesarry to align the real buffer
tmp_buffer = malloc(2*512*sizeof(char));
long align = (unsigned long)tmp_buffer%512;
printf("tmp_buffer is at: %x \% 512 = %d\n",tmp_buffer,align);

buffer = tmp_buffer+(512-align);
printf("buffer is at: %x \% 512 = %d\n",buffer,(unsigned long)buffer%512);

memset(buffer,0,sizeof(512));

// OPEN
int fd = open("/dev/sdd",O_DIRECT | O_RDWR | O_SYNC);
if(fd!=3) printf("fd = %d\n",fd);

// READ
printf("try to read and then dump buffer:\n");

r = read(fd,buffer,sizeof(512));
if(r == -1) printf("Error: %s\n",strerror(errno));
else {
// DUMP BUFFER
int i;
for(i=0; i<sizeof(512); i++)
printf("%c",buffer[i]);
}
printf("\n");
return 0;
}

输出是:

tmp_buffer is at: 1cc80010 % 512 = 16
buffer is at: 1cc80200 % 512 = 0
try to read and then dump buffer:
Error: Invalid argument

编辑:我已经按照 Brett Hale 的回答建议更新了我的来源。不幸的是我仍然得到错误。我找出 block 大小的方法可以吗?我对齐正确了吗?

非常感谢您的阅读,
费边

最佳答案

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

The O_DIRECT flag may impose alignment restrictions on the length and address of userspace buffers and the file offset of I/Os. ... Under Linux 2.6, alignment to 512-byte boundaries suffices.

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

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

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

可能有用。或者也许这种对齐方式适用于堆栈。或者,如果您使用的是 x86,则可以使用 <mm_malloc.h>内在支持功能:_mm_malloc_mm_free .

关于linux - 使用 O_DIRECT 从 HDD 读取()失败并显示 22(EINVAL,无效参数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10996539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com