Linux Direct 文件读写(文件DIO)

有时候,读写文件并不想要使用系统缓存(page cache),此时 direct 文件读写就派上了用场,使用方法:

(1)打开文件时,添加O_DIRECT参数:

需要定义_GNU_SOURCE,否则找不到O_DIRECT宏定义

示例片段:

#define _GNU_SOURCE

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int fd = open("test.out", O_RDWR | O_CREAT | O_DIRECT, 0644);

(2)读写操作的传输数据大小和缓冲区地址都需要按照一定的规则对齐:

Linux下,对于不同的文件系统和内核版本,需要的对齐边界不同,也没有统一的接口可以获取到该边界值。

对于kernel 2.4版本:传输大小和缓冲区地址均需要按照访问文件系统的逻辑块大小对齐,比如文件系统的块大小是4K,buffer地址需要按照4K对齐,需要读写4K倍数的数据

对于kernel 2.6版本:传输大小和缓冲区地址按照目标存储设备的扇区大小(一般512)对齐

可使用memalign (malloc.h)来分配指定地址对齐的资源接口:void *memalign(size_t boundary, size_t size);

完整示例程序:

#define _GNU_SOURCE

#include <sys/types.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void) {
        char hello_str[] = "Hello World!";
        void *write_buffer;
        void *read_buffer;
        int fd;
        int ret = 0;

        fd = open("test.out", O_RDWR | O_CREAT | O_DIRECT, 0644);
        if (fd < 0) {
                printf("Failed to open file\n");
                return fd;
        }   

        /* allocate a 1024 bytes buffer */
        write_buffer = memalign(512, 512 * 2); // align by 512
        if (!write_buffer) {
                printf("Failed to alloc write buffer\n");
                ret = -ENOMEM;
                goto bad_write_buffer;
        }   

        memcpy(write_buffer, hello_str, sizeof(hello_str));

        ret = write(fd, write_buffer, 512 * 2);
        if (ret < 0) {
                printf("Failed to write file\n");
                goto bad_write;
        }   

        lseek(fd, 0, SEEK_SET); // read  previous write data

        read_buffer = memalign(512, 512 * 2);
        if (!read_buffer) {
                printf("Failed to alloc read buffer\n");
                ret = -ENOMEM;
                goto bad_read_buffer;
        }

        ret = read(fd, read_buffer, 512 * 2);
        if (ret <0) {
                printf("Failed to read file\n");
                goto bad_read;
        }

        printf("read from file : %s\n", read_buffer);

bad_read:
        free(read_buffer);
bad_read_buffer:
bad_write:
        free(write_buffer);
bad_write_buffer:
        close(fd);
        return ret;
}

引用Linus的话:

"The thing that has always disturbed me about O_DIRECT is that the whole interface is just stupid, and was probably designed by a deranged monkey on some serious mind-controlling substances."—Linus(O_DIRECT就是一坨屎)

PS:

O_DIRECT的详细描述,可以看linux open系统调用的文档:http://man7.org/linux/man-pages/man2/open.2.html

时间: 2024-08-14 14:41:49

Linux Direct 文件读写(文件DIO)的相关文章

Android 如何在linux kernel 中读写文件

前言 欢迎大家我分享和推荐好用的代码段~~ 声明 欢迎转载,但请保留文章原始出处: CSDN:http://www.csdn.net 雨季o莫忧离:http://blog.csdn.net/luckkof 正文 [Description] 如何在linux kernel 中读写文件 [Keyword] linux kernel read write file 读写文件 [Solution] 通常我们只会在linux native/app 层 读写文件,但可能有一些非常特别的情况下,我们需要直接在

Android 怎样在linux kernel 中读写文件

前言 欢迎大家我分享和推荐好用的代码段~~ 声明 欢迎转载,但请保留文章原始出处: CSDN:http://www.csdn.net 雨季o莫忧离:http://blog.csdn.net/luckkof 正文 [Description] 怎样在linux kernel 中读写文件 [Keyword] linux kernel read write file 读写文件 [Solution] 通常我们仅仅会在linux native/app 层 读写文件,但可能有一些很特别的情况下,我们须要直接在

在linux内核中读写文件

http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成(C库函数实际上是对系统调用的封装). 但是,在内核态没有这样的系统调用,我们又该如何读写文件呢? 阅读Linux内核源码,可以知道陷入内核执行的是实际执行的是sys_read和sys_write这两个函数,但是这两个函数没有使用EXPORT_SYMBOL导出,也就是说其他模块不能使用. 在fs/open.c

【转】在linux内核中读写文件 -- 不错

原文网址:http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成(C库函数实际上是对系统调用的封装). 但是,在内核态没有这样的系统调用,我们又该如何读写文件呢? 阅读linux内核源码,可以知道陷入内核执行的是实际执行的是sys_read和sys_write这两个函数,但是这两个函数没有使用EXPORT_SYMBOL导出,也就是说其他模块不能使用. 在fs/o

文件读写&amp;文件夹遍历

 文件读写 读文件(行) private void readFile(File file) throws IOException { FileInputStream stream = null; stream = new FileInputStream(file); DataInputStream sysin = new DataInputStream(stream); String line = null; while ((line = sysin.readLine()) != null)

Linux i/o 读写文件

获取文件描述后,就可以对文件进行读写操作. 1.读文件 ssize_t read(int fd, void* buf, size_t len); 参数: fd:文件描述符 buf:存储读取缓存 len:预计读取的字节数 返回值: 实际读取的字节数. 描述: 调用read后,系统会从fd参数所引用文件的当前位置读取len个字节,到buf中去.返回值是写入到buf的字节数目.执行成功,返回读取的字节数:失败返回-1,并设置erron. read读取的所有可能结果: ①return == len. 正

在linux内核中读写文件2

1,内核代码 #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> #include <linux/spinlock.h> #include <linux/blkdev.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/errno.h>

简单的文件读写---文件简单的加密、解密

文件加密 package encryption; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class Encryption { //文件加密 public static void Encrypt(File file){ if(file == null){ return; } try { @SuppressWarnings("resource") Ra

python文件读写 - 文件r+ open读写实际表现

先说结论: 文件r+ open: 1. write()不能实现插入写,它总是覆盖写或附加写: 2. 如果文件一打开即write(),则从开头覆盖写; 3. 如果文件一打开,用f.seek()指定文件指针位置,然后执行f.write()则从指针位置写(覆盖写); 4. 如文件打开后先执行了readline(), 然后再执行write(),实现的是附加写 文件a+ open: 1. 文件打开后起始指针为文件末尾,readline()将读不到数据 2. write()始终是附加写 ,即使将文件指针指到

Python模块、字符编码、文件读写

模块 当我们用一种语言开始真正的软件开发室,除了编写代码外,还需要很多基本的已经写好的现成的东西,高级语言通常都会为我们提供了一个比较完善的基础代码库,让我们能直接调用,python也不例外,为我们提供了分成完善的基础代码和第三方库.在python中一个.py文件就是一个模块. 模块导入使用import 获取随机数模块 调用系统命令 把执行脚本时传递的参数获取到了 当我们试图加载一个模块时,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错,默认情况下,Python解释器会搜