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. NTP-网络时间协议

    前言 搭建了一个linux虚拟机,发现跑着跑着时间有差异,查资料发现这个是正常的,因为系统时间和硬件时间是本地时间,会因各种原因导致跟标准时间UTC时间有差异,所以计算机界的牛人发明了NTP协议,专门 ...

  2. MYSQL 源码

    http://www.cnblogs.com/wingsless/tag/MySQL/

  3. AngularJS:一行JS代码实现控件验证效果

    如上图所示,我们需要实现如下这些验证功能: 控件都是必输控件 都需要控制最大长度 第一次打开页面,控件不能显示为错误状态 输入内容再清空后,必输控件需要显示为错误状态 只有所有输入合法后,发布按钮才能 ...

  4. 3.0 - remote access 基础知识

    RA概述: remote access: 广域网的远程连接,按L1分类: 1:通过电路交换网络实现的专线:(circuit switching) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...

  5. luogu2161 [SHOI2009]会场预约

    题目大意 随着时间的推移这里有几个任务对应着一段区间.每次要将任务安到时间线上时,要把时间线上已有的与该任务对应区间有交集的区间对应的任务删去.求每次删去的区间个数,以及整个时间线上有几个任务.时间线 ...

  6. Why is try {…} finally {…} good; try {…} catch{} bad?

    http://stackoverflow.com/questions/128818/why-is-try-finally-good-try-catch-bad The big difference i ...

  7. 杂项-Java:EL表达式

    ylbtech-杂项-Java:EL表达式 EL(Expression Language) 是为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提 ...

  8. diaowen Maven Webapp

    五月 , :: 上午 org.apache.catalina.startup.VersionLoggerListener log INFO: Server version: Apache Tomcat ...

  9. md5的用处

    MD5保存摘要及指纹信息 md5的用处: 1.保存用户密码2.校验数据的完整性

  10. XML案例(使用JAXP进行SAX解析)

    1.Book.java package cn.itcast.sax; public class Book { private String name; private String author; p ...