ceph存储 Linux direct io使用
2016-04-11 13:32
686 查看
在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对齐:
或者进行手动调节对齐:
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内存数量,这对于自己本身带有缓存的应用程序(比如数据库)比较有用。
示例:
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <errno.h>
#define BUF_SIZE 1024
bool writeFileInODirectMode(long i, unsigned char *buf)
{
int fd;
int ret;
std::string fileName("./direct_io.");
char iStr[256];
sprintf(iStr, "%ld", i);
fileName.append(iStr);
fileName.append(".data");
fd = open(fileName.c_str(), O_DIRECT | O_CREAT | O_RDWR, S_IRWXU);
if (fd < 0){
perror("open ./direct_io.data failed");
free(buf);
return false;
}
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./direct_io.data failed");
return false;
}
close(fd);
return true;
}
bool writeFileInOSyncMode(long i, unsigned char *buf)
{
int fd;
int ret;
std::string fileName("./sync_io.");
char iStr[256];
sprintf(iStr, "%ld", i);
fileName.append(iStr);
fileName.append(".data");
fd = open(fileName.c_str(), O_SYNC | O_CREAT | O_RDWR, S_IRWXU);
if (fd < 0){
perror("open ./sync_io.data failed");
free(buf);
return false;
}
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./sync_io.data failed");
return false;
}
close(fd);
return true;
}
bool writeFileAndWait(long i, unsigned char *buf)
{
int fd;
int ret;
std::string fileName("./wait_io.");
char iStr[256];
sprintf(iStr, "%ld", i);
fileName.append(iStr);
fileName.append(".data");
fd = open(fileName.c_str(), O_CREAT | O_RDWR, S_IRWXU);
if (fd < 0){
perror("open ./wait_io.data failed");
free(buf);
return false;
}
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./wait_io.data failed");
return false;
}
if(fdatasync(fd) != 0)
{
perror("sync error\n");
return false;
}
close(fd);
return true;
}
int main(int argc, char * argv[])
{
unsigned char *buf;
int ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
}
memset(buf, 'c', BUF_SIZE);
if(!writeFileInODirectMode(1, buf))
{
exit(1);
}
//其他两种直写磁盘的方法
if(!writeFileInOSyncMode(2, buf))
{
exit(1);
}
if(!writeFileAndWait(3, buf))
{
exit(1);
}
free(buf);
}
在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内存数量,这对于自己本身带有缓存的应用程序(比如数据库)比较有用。
示例:
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <errno.h>
#define BUF_SIZE 1024
bool writeFileInODirectMode(long i, unsigned char *buf)
{
int fd;
int ret;
std::string fileName("./direct_io.");
char iStr[256];
sprintf(iStr, "%ld", i);
fileName.append(iStr);
fileName.append(".data");
fd = open(fileName.c_str(), O_DIRECT | O_CREAT | O_RDWR, S_IRWXU);
if (fd < 0){
perror("open ./direct_io.data failed");
free(buf);
return false;
}
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./direct_io.data failed");
return false;
}
close(fd);
return true;
}
bool writeFileInOSyncMode(long i, unsigned char *buf)
{
int fd;
int ret;
std::string fileName("./sync_io.");
char iStr[256];
sprintf(iStr, "%ld", i);
fileName.append(iStr);
fileName.append(".data");
fd = open(fileName.c_str(), O_SYNC | O_CREAT | O_RDWR, S_IRWXU);
if (fd < 0){
perror("open ./sync_io.data failed");
free(buf);
return false;
}
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./sync_io.data failed");
return false;
}
close(fd);
return true;
}
bool writeFileAndWait(long i, unsigned char *buf)
{
int fd;
int ret;
std::string fileName("./wait_io.");
char iStr[256];
sprintf(iStr, "%ld", i);
fileName.append(iStr);
fileName.append(".data");
fd = open(fileName.c_str(), O_CREAT | O_RDWR, S_IRWXU);
if (fd < 0){
perror("open ./wait_io.data failed");
free(buf);
return false;
}
ret = write(fd, buf, BUF_SIZE);
if (ret < 0) {
perror("write ./wait_io.data failed");
return false;
}
if(fdatasync(fd) != 0)
{
perror("sync error\n");
return false;
}
close(fd);
return true;
}
int main(int argc, char * argv[])
{
unsigned char *buf;
int ret = posix_memalign((void **)&buf, 512, BUF_SIZE);
if (ret) {
perror("posix_memalign failed");
exit(1);
}
memset(buf, 'c', BUF_SIZE);
if(!writeFileInODirectMode(1, buf))
{
exit(1);
}
//其他两种直写磁盘的方法
if(!writeFileInOSyncMode(2, buf))
{
exit(1);
}
if(!writeFileAndWait(3, buf))
{
exit(1);
}
free(buf);
}
相关文章推荐
- linux下cat命令详解
- Linux下Varnish缓存服务器的安装与配置教程
- linux g++以及build-essential 安装问题
- linux 查看程序是否运行
- linux查看某个端口被占用
- vultr centos x64 6.5.x 升级php7.0
- centos 下 mysql 安装配置
- linux 防火墙打开端口/屏蔽IP等
- Linux中变量$#,$@,$0,$1,$2,$*,$$,$?的含义
- Centos 7 密码破解
- centos7 通过kvm+vnc 实现远程桌面虚拟化和创建windows、Linux虚拟机
- Centos 6.5 密码破解
- CentOS 6 安装Hadoop 2.6 (三)问题收集
- CentOS 7 中 hostnamectl 的使用
- 申请红帽企业版Linux开发者订阅
- Linux下检测内存泄漏工具Valgrind
- linux 内存泄漏检查工具
- 深入解析Linux系统中的SELinux访问控制功能
- 在linux下用不了ifconfig的问题
- CentOS 6 安装Hadoop 2.6 (二)配置Hadoop