Linux direct io使用

在linux 2.6内核上使用direct io不难,只需按照如下几点来做即可:

1,在open文件时加上O_DIRECT旗标,这样以通告内核我们想对该文件进行直接io操作。

2,在源文件的最顶端加上_GNU_SOURCE宏定义,或在编译时加在命令行上也可以,否则将提示:

direct_io_write_file.c: In function 'main':
direct_io_write_file.c:25: error: 'O_DIRECT' undeclared (first use in this function)
direct_io_write_file.c:25: error: (Each undeclared identifier is reported only once
direct_io_write_file.c:25: error: for each function it appears in.)

3,存放文件数据的缓存区起始位置以及每一次读写数据长度必须是磁盘逻辑块大小的整数倍,一般也就是512字节(也有可能是一内存页大小,4096),否则将导致read/write失败,perror将提示:read failed: Invalid argument或write failed: Invalid argument。

1和2很容易做到,而第3点,要满足缓存区起始位置与512对齐,这可以在进行缓存区空间申请时使用posix_memalign这样的函数指定512对齐:

ret = posix_memalign((void **)&buf, 512, BUF_SIZE);

或者进行手动调节对齐:

real_buf = malloc(BUF_SIZE + 512);
aligned_buf = ((((unsigned int)real_buf + 512 - 1) / 512) * 512);

由于要满足每一次读写数据长度必须是磁盘逻辑块大小的整数倍,所以最后一次文件操作可能无法满足,此时只能重新以cached io模式打开文件后,fseek到对应位置进行剩余数据的读写。

为什么要使用direct io?因为direct io不过文件系统缓冲,也就是说对文件进行direct io操作不会减少系统的free内存数量,这对于自己本身带有缓存的应用程序(比如数据库)比较有用。

示例:

/**
* gcc cached_io_read_file.c -o cached_io_read_file -D_GNU_SOURCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define BUF_SIZE 1024 int main()
{
int fd;
int ret;
unsigned char *buf;
ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
} fd = open("./direct_io.data", O_RDONLY, 0755);
if (fd < 0){
perror("open ./direct_io.data failed");
free(buf);
exit(1);
} do {
ret = read(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("read ./direct_io.data failed");
}
} while (ret > 0); free(buf);
close(fd);
}
/**
* gcc cached_io_write_file.c -o cached_io_write_file -D_GNU_SOURCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define BUF_SIZE 1024 int main(int argc, char * argv[])
{
int fd;
int ret;
unsigned char *buf;
ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
}
memset(buf, 'c', BUF_SIZE); fd = open("./direct_io.data", O_WRONLY | O_CREAT, 0755);
if (fd < 0){
perror("open ./direct_io.data failed");
free(buf);
exit(1);
} do {
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./direct_io.data failed");
}
} while (1); free(buf);
close(fd);
}

/**
* gcc direct_io_read_file.c -o direct_io_read_file -D_GNU_SOURCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define BUF_SIZE 1024 int main()
{
int fd;
int ret;
unsigned char *buf;
ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
} fd = open("./direct_io.data", O_RDONLY | O_DIRECT, 0755);
if (fd < 0){
perror("open ./direct_io.data failed");
exit(1);
} do {
ret = read(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./direct_io.data failed");
}
} while (ret > 0); free(buf);
close(fd);
}

/**
* gcc direct_io_write_file.c -o direct_io_write_file -D_GNU_SOURCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define BUF_SIZE 1024 int main(int argc, char * argv[])
{
int fd;
int ret;
unsigned char *buf;
ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
}
memset(buf, 'c', BUF_SIZE); fd = open("./direct_io.data", O_WRONLY | O_DIRECT | O_CREAT, 0755);
if (fd < 0){
perror("open ./direct_io.data failed");
exit(1);
} do {
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./direct_io.data failed");
}
} while (1); free(buf);
close(fd);
}
/**
* gcc direct_io_read_write_file.c -o direct_io_read_write_file -D_GNU_SOURCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define BUF_SIZE 1024 int main(int argc, char * argv[])
{
int fd, fd1;
int ret;
unsigned char *buf;
ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
}
memset(buf, 'c', BUF_SIZE); fd = open("/dev/sda", O_RDONLY | O_DIRECT | O_LARGEFILE, 0755);
if (fd < 0){
perror("open /dev/sda failed");
exit(1);
} fd1 = open("./direct_io.data", O_WRONLY | O_DIRECT | O_CREAT, 0755);
if (fd1 < 0){
perror("open ./direct_io.data failed");
close(fd);
exit(1);
} do {
ret = read(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("read /dev/sda failed");
}
ret = write(fd1, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./direct_io.data failed");
}
} while (1); free(buf);
close(fd);
close(fd1);
}

Linux direct io使用例子的更多相关文章

  1. MMAP和DIRECT IO区别

    看完此文,题目不言自明.转自 http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的东西,技术人员非常关 ...

  2. Linux的io机制

    Linux的io机制 Buffered-IO 和Direct-IO Linux磁盘I/O分为Buffered IO和Direct IO,这两者有何区别呢? 对于Buffered IO: 当应用程序尝试 ...

  3. MMAP和DIRECT IO区别【转】

    转自:http://www.cnblogs.com/zhaoyl/p/5901680.html 看完此文,题目不言自明.转自 http://blog.chinaunix.net/uid-2710571 ...

  4. Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式

    Linux就这个范儿 第15章 七种武器  linux 同步IO: sync.fsync与fdatasync   Linux中的内存大页面huge page/large page  David Cut ...

  5. Linux磁盘IO监控[zz]

    磁盘 I/O 监控是 Unix/Linux 系统管理中一个非常重要的组成部分.它可以监控吞吐量.每秒 I/O 数.磁盘利用率.服务时间等信息,并且在发现异常时,发送告警信息给系统管理员,便于系统管理员 ...

  6. Linux Network IO Model、Socket IO Model - select、poll、epoll

    目录 . 引言 . IO机制简介 . 阻塞式IO模型(blocking IO model) . 非阻塞式IO模型(noblocking IO model) . IO复用式IO模型(IO multipl ...

  7. Linux的IO调度

    Linux的IO调度 IO调度发生在Linux内核的IO调度层.这个层次是针对Linux的整体IO层次体系来说的.从read()或者write()系统调用的角度来说,Linux整体IO体系可以分为七层 ...

  8. 通过iostat来查看linux硬盘IO性能|实例分析

    iostat查看linux硬盘IO性能 rrqm/s: 每秒进行 merge 的读操作数目.即 delta(rmerge)/s wrqm/s: 每秒进行 merge 的写操作数目.即 delta(wm ...

  9. bufferIO,Direct io,mmap, ZeroCopy

    1 bufferIO(传统IO),Direct io(干掉内核cache),mmap(大数据映射),zeroCopy(网络IO) 2 linux 5种IO 3NIO 相关知识 这张图展示了mmap() ...

随机推荐

  1. Tomcat类载入器机制(Tomcat源代码解析六)

    要说Tomcat的Classloader机制,我们还得从Bootstrap開始.在BootStrap初始化的时候.调用了org.apache.catalina.startup.Bootstrap#in ...

  2. 使用markdown和gitblog搭建自己的博客

    GitBlog官网 GitBlog文档 Gitblog官方QQ群:84692078 GitBlog是一个简单易用的Markdown博客系统.它不须要数据库,没有管理后台功能,更新博客仅仅须要加入你写好 ...

  3. c++ 基于Policy 的 模板编程

    在没真正接触c++  模板编程之前.真的没有想到c++ 还能够这么用.最大的感触是:太灵活了,太强大了. 最初接触模板威力还是在Delta3d中,感觉里面的模板使用实在是灵活与方便,特别是dtAI中使 ...

  4. 浅析android适配器adapter中的那些坑

    做项目中遇到的,折磨了我将近两天,今天把经验分享出来.让大家以后少走点弯路,好了.简单来说一下什么是android的适配器,怎样定义.怎样添加适配器的重用性.怎样去减少程序的耦合性 适配器顾名思义是用 ...

  5. oc50--@class1

    // // main.m #import <Foundation/Foundation.h> #import "Person.h" int main(int argc, ...

  6. 97. ExtJS之EditorGridPanel afteredit属性

    转自:https://zccst.iteye.com/blog/1328869 1. 之前大多用Ext.grid.GridPanel,现在需要可编辑功能,发现比以前稍复杂一些. 就是需要对指定列进行可 ...

  7. PCB Genesis脚本C#使用WPF窗体实现方法

    用C#写脚本做UI界面基本上都是用WinForm界面,如果想制作很漂亮动态的界面用WPF界面挺不错的选择, 这里介绍如何使用控制台程序调用WPF窗口 一.方法一 在控制台程序中,通过Main方法启动W ...

  8. A simple problem(并查集判环)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2497 题意:给定一些点和边的关系,判断S点是否 ...

  9. thinkphp session db配置

    这篇文章主要介绍了ThinkPHP实现将SESSION存入MYSQL的方法,需要的朋友可以参考下   本文以实例讲解了ThinkPHP实现将SESSION存入MYSQL的方法,所采用的运行环境是Thi ...

  10. docker(一):docker是什么?

    认识容器:docker入门篇 docker是什么? Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚 ...