Linux Native AIO

来看看 Linux 提供的 AIO 系统调用(自行封装的头文件 native_aio.h):

#ifndef __NATIVE_AIO_H__

#define __NATIVE_AIO_H__

#define _GNU_SOURCE

#include

#include

#include

#include

static inline int io_setup(unsigned nr_events, aio_context_t* ctx_idp)

{

return syscall(__NR_io_setup, nr_events, ctx_idp);

}

static inline int io_destroy(aio_context_t ctx)

{

return syscall(__NR_io_destroy, ctx);

}

static inline int io_submit(aio_context_t ctx, long nr, struct iocb** iocbpp)

{

return syscall(__NR_io_submit, ctx, nr, iocbpp);

}

static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,

struct io_event* events, struct timespec* timeout)

{

return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);

}

static inline int io_cancel(aio_context_t ctx, struct iocb* iocb,

struct io_event* result)

{

return syscall(__NR_io_cancel, ctx, iocb, result);

}

#endif

通过 man 能够查到函数的描述,但是这些函数不是跨平台的,因此 libc 没有对这些函数进行封装,这里手动封装了一下。下面是一个使用示例:

#include "native_aio.h"

#include

#include

#include

#include

#include

#define NR_EVENT 1024

#define BUFSIZE 4096

int main(void)

{

int fd, ret = -1;

char* buf;

aio_context_t ctx;

struct io_event event;

struct iocb cb;

struct iocb* cblist[] = {&cb};

fd = open(__FILE__, O_RDONLY | O_DIRECT);

if (fd == -1) {

fprintf(stderr, "open(%s) failed: %s.\n", __FILE__, strerror(errno));

return -1;

}

buf = aligned_alloc(512, BUFSIZE);

if (!buf) {

fprintf(stderr, "aligned_alloc(%u) failed: %s.\n", BUFSIZE,

strerror(errno));

goto err1;

}

memset(&ctx, 0, sizeof(ctx));

ret = io_setup(NR_EVENT, &ctx);

if (ret != 0) {

fprintf(stderr, "io_setup failed: %s.\n", strerror(errno));

goto err2;

}

memset(&cb, 0, sizeof(cb));

cb.aio_data = (__u64)buf;

cb.aio_fildes = fd;

cb.aio_lio_opcode = IOCB_CMD_PREAD;

cb.aio_buf = (__u64)buf;

cb.aio_offset = 0;

cb.aio_nbytes = BUFSIZE;

ret = io_submit(ctx, 1, cblist);

if (ret != 1) {

fprintf(stderr, "io_submit failed: %s.\n", strerror(errno));

goto err3;

}

ret = io_getevents(ctx, 1, 1, &event, NULL);

if (ret != 1) {

fprintf(stderr, "io_getevents failed: %s.\n", strerror(errno));

goto err3;

}

if (event.res <= 0) {

fprintf(stderr, "io error: %s.\n", strerror(-(event.res)));

} else {

printf("read %lld byte(s):\n", event.res);

write(1, (const void*)(event.data), event.res);

}

err3:

io_destroy(ctx);

err2:

free(buf);

err1:

close(fd);

return ret;

}

程序首先打开一个只读文件,注意这里加了选项“O_DIRECT”,直接从磁盘读取文件。因为绕过了 page cache,所以一般程序都会自己来实现 cache;接着使用 aligned_alloc() 申请存放读取内容的 buffer,起始地址需要和磁盘逻辑块大小对齐(一般是 512 字节)。

准备工作完成后,调用 io_setup() 来初始化一个 aio_context_t 标识符,用于后续的 aio 操作。描述 aio 信息的主要是结构体 struct iocb(在 /usr/include/linux/aio_abi.h 中定义):

struct iocb {

/* these are internal to the kernel/libc. */

__u64 aio_data; /* data to be returned in event's data */

__u32 PADDED(aio_key, aio_reserved1);

/* the kernel sets aio_key to the req # */

/* common fields */

__u16 aio_lio_opcode; /* see IOCB_CMD_ above */

__s16 aio_reqprio;

__u32 aio_fildes;

__u64 aio_buf;

__u64 aio_nbytes;

__s64 aio_offset;

/* extra parameters */

__u64 aio_reserved2; /* TODO: use this for a (struct sigevent *) */

/* flags for the "struct iocb" */

__u32 aio_flags;

/*

* if the IOCB_FLAG_RESFD flag of "aio_flags" is set, this is an

* eventfd to signal AIO readiness to

*/

__u32 aio_resfd;

}; /* 64 bytes */

需要填充的字段包括:

aio_data:事件完成后随着 struct io_event 返回的内容,后面详细介绍;

aio_lio_opcode:IO 类型,可能包含以下取值:

IOCB_CMD_PREAD:对应系统调用 pread(),读取从指定位置开始的指定长度的内容,但是不改变文件偏移;

IOCB_CMD_PWRITE:对应系统调用 pwrite(),从指定位置写入指定长度的内容,但是不改变文件偏移;

IOCB_CMD_FSYNC:对应系统调用 fsync(),将元数据和文件内容写到磁盘;

IOCB_CMD_FDSYNC:对应 fdatasync(),将文件内容和必需的元数据写到磁盘;

IOCB_CMD_NOOP:不确定,据说还没被使用;

IOCB_CMD_PREADV:对应 preadv(),从当前位置读取指定数量和长度的 buffer,但不改变文件偏移;

IOCB_CMD_PWRITEV:对应 pwritev(),从当前位置写入指定数量和长度的 buffer,但不改变文件偏移。

aio_fildes:要操作的文件描述符;

aio_buf:要操作的 buffer 起始地址;

aio_nbytes:要读写的长度;

aio_offset:要读写的起始位置。

其它字段一定要置 0。

填充完成后就可以调用 io_submit() 提交请求了,请求提交后 io_submit() 会立即返回。接着可以调用 io_getevents() 获取在 aio_context_t 上提交的事件,函数的第二个参数是最少需要获取多少个事件,第三个参数是最多获取多少个事件,第四个参数是超时设置,如果超过指定事件还没等到最少个数的事件就返回,返回值就是实际返回的事件个数。

从 io_getevents() 返回后从 struct io_event 获取事件执行的结果:

struct io_event {

__u64 data; /* the data field from the iocb */

__u64 obj; /* what iocb this event came from */

__s64 res; /* result code for this event */

__s64 res2; /* secondary result */

};

其中的 data 字段就是 struct iocb 里的 aio_data;obj 就是 iocb 本身;res 小于等于 0 表示出错,-res 的值就是 errno,res 大于 0 表示读写成功的字节数;res2 不知道干啥用的。

最后用 io_destroy() 释放资源。

参考资料

linux aio参数,Linux 异步 IO 之 Native AIO相关推荐

  1. linux 内核io操作,关于Linux内核中的异步IO的使用

    我们都知道异步IO的作用,就是可以提高我们程序的并发能力,尤其在网络模型中.在linux中有aio的一系列异步IO的函数接口,但是这类函数都是glibc库中的函数,是基于多线程实现,不是真正的异步IO ...

  2. linux aio参数,LINUX AIO

    从Oracle9iR2开始支持Linux上的异步IO,但是Oracle9iR2和Oracle10gR1中的AIO模块默认是disable的,如果要启用必须relink一下 cd $ORACLE_HOM ...

  3. linux aio参数,linux内核aio功能

    我正在测试内核异步io函数(而不是posix aio),并试图弄清楚它是如何工作的.下面的代码是一个完整的程序,我只需将一个数组重复写入使用O_DIRECT打开的文件.我在回调函数"writ ...

  4. linux 启动 参数,Linux启动参数

    Linux启动参数 发布时间:2008-09-03 15:46:31来源:红联作者:Sednol linux noapic (跳过硬件检测) linux pci=noapic (跳过PCI卡部分硬件检 ...

  5. Linux系统Posix异步IO接口(aio.h):aio_read,aio_write,aio_error

    目录 aio_read.c aio_write.c aio_suspend.c lio_listio.c 相关文章 aio_read.c #include<stdio.h> #includ ...

  6. linux操作系统之全局异步IO及可重入/不可重入函数

    (1)全局变量异步I/O实现父子进程交替数数 1)信号捕捉函数 2)main函数实现信号交替 3)程序实现 1>创建子进程,父进程等待1s,等待子进程完成捕捉函数注册(捕捉信号SIGUSR1). ...

  7. linux getline参数,Linux下的getline函数

    最近在做国嵌的mp3项目,在mp3主控程序中用到了这个函数,挺好使的,在这里记录一下.注意是linux下的,不是C++中的. 函数原型 ssize_t getline(char **lineptr, ...

  8. linux fg 参数,Linux的bg和fg命令简单介绍

    我们都知道,在 Windows 上面,我们要么让一个程序作为服务在后台一直运行,要么停止这个服务.而不能让程序在前台后台之间切换.而 Linux 提供了 fg 和 bg 命令,让我们轻松调度正在运行的 ...

  9. linux方法参数,Linux的sysctl 命令 参数

    Linux内核通过/proc虚拟文件系统向用户导出内核信息,用户也可以通过/proc文件系统或通过sysctl命令动态配置内核.比如,如果我们想启动NAT,除了加载模块.配置防火墙外,还需要启动内核转 ...

最新文章

  1. c++矩阵转置_C语言:数据结构-稀疏矩阵的压缩存储
  2. 10 个十分难得的 javascript 开发经验
  3. 八、Pandas的基本使用
  4. git 创建webpack项目_webpack项目的搭建及环境构建
  5. 虚拟机VMware Workstation安装Linux服务器Debian11系统详细教程
  6. 读梁宁《一次失控引发的信任评估---我看胡紫薇事件》
  7. .NET采集数据,放入数据库总结
  8. 我有一张1996年版一元钱,值多少钱?
  9. 51Nod-1001 数组中和等于K的数对【排序+二分查找】
  10. 利用R语言ggplot2包制作金字塔图,展示人口结构数据
  11. 【Android驱动】屏和TP谁先休眠的问题
  12. 21届校招中获得12家公司offer的一些经验(包括6家银行信息科技岗offer)
  13. SSR、SSE、SST、判定系数(可决系数、拟合优度)的计算公式
  14. RuntimeError: mat1 and mat2 shapes cannot be multiplied (192x64 and 4x3)
  15. java纲要_幼儿园综合素质笔试大纲
  16. 【H5游戏】-整一个简单的解压小游戏【抽纸巾】
  17. C# Environment.StackTrace、StackFrame、Tirm的使用技巧
  18. PowerPoint如何找回隐藏的iSlide设计工具
  19. vba二维数组初始化_VBA二维数组的基础介绍
  20. windows重装 启动时找不到安装盘 装系统时有盘解决

热门文章

  1. 谷歌扩招又扩建,又一波招聘高峰要来了?
  2. IOS XCode 控制台打印中文方法
  3. 解决SecureCRT(linux远程访问工具)中中文乱码问题
  4. 测试适合什么颜色衣服的软件,形象顾问 | 超准的颜色测试!一语道破你最适合穿什么颜色的衣服!...
  5. 生物神经网络与机器学习的碰撞,Nature论文提出DNA试管网络识别手写数字
  6. 西北工业大学计算机学硕复试,分享:西北工业大学计算机考研复试经验_跨考网...
  7. linux和鸿蒙的区别和联系,华为鸿蒙与linux关系
  8. 句句名言,虽然是写给女生的,但是,男生也更应该看看。
  9. C:\Users\Kelly\AppData\Roaming\npm-cache\_logs\2019-03-24T08_17_24_284Z-debug.log
  10. python阿凡提麦子问题_第142期-阿凡提系列幽默笑话二十则