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. VC ON_CONTROL_RANGE多个控件响应一个方法

    步骤/方法 分三个步骤 在头文件里声明函数比如 afx_msg void onNum(UINT uID) 在.cpp文件里加入函数体 void CCalculatorDlg::OnNum(UINT u ...

  2. vue组件的一个总结

    用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...

  3. Oracle GoldenGate从oracle db 到非oracle db的初始化数据同步的方法

    非oracle db以 sqlserver为样例说明: 我的思路 A :oracle db 生产  B: oracle db 中间机 C: sqlserver db 目的端 A-> B-> ...

  4. oc35--自定义构造方法

    // // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property int ag ...

  5. linux中两个缓冲区

    不同于Windows,Linux系统里存在两个剪切板:一个叫做选择缓冲区(X11 selection buffer),另一个才是剪切板(clipboard). 01)选择缓冲区(缓冲内容在其他位置可用 ...

  6. python pickle to json

    ref: https://gist.github.com/Samurais/567ebca0f59c612eb977065008aad867 ''' Convert a pkl file into j ...

  7. iOS版本、iPhone版本、Xcode版本比对

    iOS版本 iPhone版本 Xcode版本 其他 2003年 Xcode1.0 2005年4月29日 Xcode2.0 2007年1月9日 iPhone OS(iOS1): 虚拟键盘.谷歌地图 第一 ...

  8. vim gvim技巧大全(9)(转载)

    vim gvim技巧大全(9) 2 用命令}移动到这个段落的底部,标记为b3 输入命令:'a,'b move来移动文本.老版本的Vi编辑器不能很好的来处理多文件.但是Vim在处理多文件上却显得优秀得多 ...

  9. PCB Genesis增加轮廓字 实现原理

    在Genesis增加汉字自带是不支持增加汉字的,如果需增加汉字需用到CAD 汉字库才可增加汉字,这里介绍一种脱离汉字库实现 Genesis增加轮廓字(如要变为实体,填空Surface可变为实体字) 一 ...

  10. selenium3 + python 操作浏览器基本方法

    from selenium import webdriverimport time as t # driver = webdriver.Chrome()# driver.get("http: ...