从使用 O_DIRECT 打开的文件中搜索 () 和读取 ()
seek() and read() from a file opened with O_DIRECT
我正在尝试从文件中 seek
和 read
,而我的 objective 是所有读取都直接来自磁盘。为了做到这一点,我 open()
文件 O_DIRECT
, lseek()
到所需的偏移量,并尝试从磁盘 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?我们如何寻找不同的磁盘偏移并直接从磁盘读取?
“适当对齐”是这里的关键。您需要确保您的偏移量是 4k(页面大小)对齐的。此外,大小需要是 4k 的倍数。
我正在尝试从文件中 seek
和 read
,而我的 objective 是所有读取都直接来自磁盘。为了做到这一点,我 open()
文件 O_DIRECT
, lseek()
到所需的偏移量,并尝试从磁盘 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?我们如何寻找不同的磁盘偏移并直接从磁盘读取?
“适当对齐”是这里的关键。您需要确保您的偏移量是 4k(页面大小)对齐的。此外,大小需要是 4k 的倍数。