我正在努力寻找如何正确使用pread和pwrite的方法。 在这种情况下,我尝试使用pread读取256个字节。 但是,每当我尝试读取少于512字节的pread时,都不会返回任何内容。 我认为这个问题必须与我分配给posix_memalign的SECTOR参数有关。
我需要注意一些明显的信息吗?
#define BUF_SIZE 256
#define SECTOR 512
#define FILE_SIZE 1024 * 1024 * 1024 //1G
int main( int argc, char **argv ){
int fd, nr;
char fl_nm[]={"/dev/nvme0n1p1"};
char* aligned_buf_w = NULL;
char* aligned_buf_r = NULL;
void* ad = NULL;
if (posix_memalign(&ad, SECTOR, BUF_SIZE)) {
perror("posix_memalign failed"); exit (EXIT_FAILURE);
}
aligned_buf_w = (char *)(ad);
ad = NULL;
if (posix_memalign(&ad, SECTOR, BUF_SIZE)) {
perror("posix_memalign failed"); exit (EXIT_FAILURE);
}
aligned_buf_r = (char *)(ad);
memset(aligned_buf_w, '*', BUF_SIZE * sizeof(char));
printf("BEFORE READ BEGIN\n");
printf("\t aligned_buf_w::%ld\n",strlen(aligned_buf_w));
printf("\t aligned_buf_r::%ld\n",strlen(aligned_buf_r));
printf("BEFORE READ END\n");
fd = open(fl_nm, O_RDWR | O_DIRECT);
pwrite(fd, aligned_buf_w, BUF_SIZE, 0);
//write error checking
if(nr == -1){
perror("[error in write 2]\n");
}
nr = pread(fd, aligned_buf_r, BUF_SIZE, 0);
//read error checking
if(nr == -1){
perror("[error in read 2]\n");
}
printf("AFTER READ BEGIN\n");
printf("\taligned_buf_r::%ld \n",strlen(aligned_buf_r));
printf("AFTER READ END\n");
//error checking for close process
if(close(fd) == -1){
perror("[error in close]\n");
}else{
printf("[succeeded in close]\n");
}
return 0;
}
这是我读写512字节时的输出
BEFORE READ BEGIN
aligned_buf_w::512
aligned_buf_r::0
BEFORE READ END
AFTER READ BEGIN
aligned_buf_r::512
AFTER READ END
[succeeded in close]
这是我尝试读取256个字节时的结果
BEFORE READ BEGIN
aligned_buf_w::256
aligned_buf_r::0
BEFORE READ END
[error in read 2]
: Invalid argument
AFTER READ BEGIN
aligned_buf_r::0
AFTER READ END
[succeeded in close]
答案 0 :(得分:2)
512B是您可以从存储设备读取的最小单元
答案 1 :(得分:2)
使用O_DIRECT时,“内核将直接在作为参数传递的用户空间缓冲区所指向的物理内存之间/直接对DMA进行DMA”-https://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html-因此,您必须遵守一些限制-http://man7.org/linux/man-pages/man8/raw.8.html >
所有I / O必须在内存和磁盘上正确对齐:它们必须从一个扇区开始 磁盘上的偏移量,它们必须是扇区的确切数目,并且 虚拟内存中的数据缓冲区还必须对齐 部门规模。大多数设备的扇区大小为512字节。
使用缓冲的IO无需理会。以下示例说明了在读取HDD(/ dev / sda9)时的情况:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SECTOR 512
int main( int argc, char **argv ){
int fd, nr, BUF_SIZE;
char fl_nm[]={"/dev/sda9"};
char* buf = NULL;
if (argc>1) {
BUF_SIZE = atoi(argv[1]);
// BUFFERED IO
printf("Buffered IO -------\n");
if ((buf = (char*)malloc(BUF_SIZE)) == NULL) perror("[malloc]");
else {
if ((fd = open(fl_nm, O_RDONLY)) == -1) perror("[open]");
if((nr = pread(fd, buf, BUF_SIZE, 4096)) == -1) perror("[pread]");
else
printf("%i bytes read %.2x %.2x ...\n",nr,buf[0],buf[1]);
free(buf);
if(close(fd) == -1) perror("[close]");
}
// DIRECT IO
printf("Direct IO ---------\n");
if (posix_memalign((void *)&buf, SECTOR, BUF_SIZE)) {
perror("posix_memalign failed");
}
else {
if ((fd = open(fl_nm, O_RDONLY | O_DIRECT)) == -1) perror("[open]");
/* buf size , buf alignment and offset has to observe hardware restrictions */
if((nr = pread(fd, buf, BUF_SIZE, 4096)) == -1) perror("[pread]");
else
printf("%i bytes read %.2x %.2x ...\n",nr,buf[0],buf[1]);
free(buf);
if(close(fd) == -1) perror("[close]");
}
}
return 0;
}
您可以验证以下行为:
$ sudo ./testodirect 512
Buffered IO -------
512 bytes read 01 04 ...
Direct IO ---------
512 bytes read 01 04 ...
$ sudo ./testodirect 4
Buffered IO -------
4 bytes read 01 04 ...
Direct IO ---------
[pread]: Invalid argument
O_DIRECT并不适合所有人https://yarchive.net/comp/linux/o_direct.html