【问题标题】:seek() and read() from a file opened with O_DIRECT使用 O_DIRECT 打开的文件中的 seek() 和 read()
【发布时间】:2020-10-25 03:58:52
【问题描述】:

我正在尝试从文件中读取seekread,我的目标是所有读取都直接来自磁盘。为了做到这一点,我将open()O_DIRECTlseek() 的文件添加到所需的偏移量,并尝试将read() 从磁盘中取出一个块。从磁盘读取时遇到错误:

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

int main(int argc, char *argv[])
{
        int disk_fd_read;
        off_t disk_off;
        int ret;

        int next_block;

        disk_fd_read = open(argv[1], O_RDONLY | O_DIRECT);
        if (disk_fd_read < 0) {
                printf("disk open error: %s\n", strerror(errno));
                exit(1);
        }

        disk_off = 100;

        disk_off = lseek(disk_fd_read, disk_off, SEEK_SET);
        if (disk_off != 100 || disk_off < 0) {
                printf("Error: could not seek %s\n", strerror(errno));
                exit (1);
        }
        printf("disk offset = %ld\n", disk_off);
        ret = read(disk_fd_read, &next_block, sizeof(uint64_t));
        /* 
        pread does not work either...
        ret = pread(disk_fd_read, &next_block, sizeof(uint64_t), disk_off);
        */
        if( ret == -1) {
                printf("error reading from device %s\n",strerror(errno));
                exit(1);
        }
        close(disk_fd_read);
}

/* RUN:
dd if=/dev/zero of=1Mfile bs=1M count=1
./a.out 1Mfile
disk offset = 100
error reading from device Invalid argument
*/

当我在打开文件时删除 O_DIRECT 时错误消失。从阅读手册页:

    EINVAL fd  is attached to an object which is unsuitable for reading; or the file was 
opened with the O_DIRECT flag, and either the address specified in buf, the value specified 
in count, or the current file offset is not suitably aligned.

这是否意味着 lseek 不支持 O_DIRECT?我们如何寻找不同的磁盘偏移量并直接从磁盘读取?

【问题讨论】:

  • 在未先检查argc 以确保用户实际输入命令行参数之前,切勿访问argv[0] 以外的地方

标签: c linux file unix lseek


【解决方案1】:

“适当对齐”是这里的关键。您需要确保您的偏移量是 4k(页面大小)对齐的。此外,大小需要是 4k 的倍数。

【讨论】:

  • 谢谢你,跟进:我将磁盘偏移量更改为 4k,我在 char 缓冲区中读取了 4k 字节(这使得 count 中指定的值与当前文件偏移量页面大小对齐)。我仍然得到错误,我相信是因为我不知道如何将buf中的地址对齐到4k?我目前使用 char buf[4096] 并将数据读入缓冲区。
  • this 帮助使用 memaligned 地址。代码现在可以工作了。谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
相关资源
最近更新 更多