Linux下原生异步IO接口Libaio的用法
Posted on June 15, 2011 by Jian Zhou
libaio是linux下原生的异步IO接口。网上对其使用方法讨论较少,这里做个简单说明。libaio的使用并不复杂,过程为:libaio的初始化,io请求的下发和回收,libaio销毁。
一、libaio接口
libaio提供下面五个主要API函数:
int io_setup(int maxevents, io_context_t *ctxp);
int io_destroy(io_context_t ctx);
int io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
int io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
五个宏定义:
void io_set_callback(struct iocb *iocb, io_callback_t cb);
void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset);
void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset);
void io_prep_pwritev(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset);
void io_prep_preadv(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset);
这五个宏定义都是操作struct iocb的结构体。struct iocb是libaio中很重要的一个结构体,用于表示IO,但是其结构略显复杂,为了保持封装性不建议直接操作其元素而用上面五个宏定义操作。
二、libaio的初始化和销毁
观察libaio五个主要API,都用到类型为io_context的变量,这个变量为libaio的工作空间。不用具体去了解这个变量的结构,只需要了解其相关操作。创建和销毁libaio分别用到io_setup(也可以用io_queue_init,区别只是名字不一样而已)和io_destroy。
int io_setup(int maxevents, io_context_t *ctxp);
int io_destroy(io_context_t ctx);
三、libaio读写请求的下发和回收
1. 请求下发
libaio的读写请求都用io_submit下发。下发前通过io_prep_pwrite和io_prep_pread生成iocb的结构体,做为io_submit的参数。这个结构体中指定了读写类型、起始扇区、长度和设备标志符。
libaio的初始化不是针对一个具体设备进行初始,而是创建一个libaio的工作环境。读写请求下发到哪个设备是通过open函数打开的设备标志符指定。
2. 请求返回
读写请求下发之后,使用io_getevents函数等待io结束信号:
int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
io_getevents返回events的数组,其参数events为数组首地址,nr为数组长度(即最大返回的event数),min_nr为最少返回的events数。timeout可填NULL表示无等待超时。io_event结构体的声明为:
struct io_event {
    PADDEDptr(void *data, __pad1);
    PADDEDptr(struct iocb *obj,  __pad2);
    PADDEDul(res,  __pad3);
    PADDEDul(res2, __pad4);
};
其中,res为实际完成的字节数;res2为读写成功状态,0表示成功;obj为之前下发的struct iocb结构体。这里有必要了解一下struct iocb这个结构体的主要内容:
iocbp->iocb.u.c.nbytes 字节数
iocbp->iocb.u.c.offset 偏移
iocbp->iocb.u.c.buf 缓冲空间
iocbp->iocb.u.c.flags 读写
3. 自定义字段
struct iocb除了自带的元素外,还留有供用户自定义的元素,包括回调函数和void *的data指针。如果在请求下发前用io_set_callback绑定用户自定义的回调函数,那么请求返回后就可以显示的调用该函数。回调函数的类型为:
void callback_function(io_context_t ctx, struct iocb *iocb, long res, long res2);
另外,还可以通过iocbp->data指针挂上用户自己的数据。
注意:实际使用中发现回调函数和data指针不能同时用,可能回调函数本身就是使用的data指针。
四、使用例子
通过上面的说明并不能完整的了解libaio的用法,下面通过简单的例子进一步说明。
#include <stdlib.h>
#include <stdio.h>
#include <libaio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libaio.h>
int srcfd = -1;
int odsfd = -1;
#define AIO_BLKSIZE  1024
#define AIO_MAXIO 64
static void wr_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
    if (res2 != 0) {
        printf("aio write error n");
    }
    if (res != iocb->u.c.nbytes) {
        printf("write missed bytes expect % d got % d n", iocb->u.c.nbytes, res);
        exit(1);
    }
    free(iocb->u.c.buf);
    free(iocb);
}
static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
    
    int iosize = iocb->u.c.nbytes;
    char *buf = (char *)iocb->u.c.buf;
    off_t offset = iocb->u.c.offset;
    int tmp;
    char *wrbuff = NULL;
    if (res2 != 0) {
        printf("aio read n");
    }
    if (res != iosize) {
        printf("read missing bytes expect % d got % d", iocb->u.c.nbytes, res);
        exit(1);
    }
    
    tmp = posix_memalign((void **)&wrbuff, getpagesize(), AIO_BLKSIZE);
    if (tmp < 0) {
        printf("posix_memalign222 n");
        exit(1);
    }
    snprintf(wrbuff, iosize + 1, "%s", buf);
printf("wrbuff - len = %d:%s n", strlen(wrbuff), wrbuff);
    printf("wrbuff_len = %d n", strlen(wrbuff));
    free(buf);
    io_prep_pwrite(iocb, odsfd, wrbuff, iosize, offset);
    io_set_callback(iocb, wr_done);
    if (1 != (res = io_submit(ctx, 1, &iocb)))
        printf("io_submit write error n");
    printf("nsubmit % d write request n", res);
}
void main(int args, void *argv[])
{
    int length = sizeof("abcdefg");
    char *content = (char *)malloc(length);
    io_context_t myctx;
    int rc;
    char *buff = NULL;
    int offset = 0;
    int num, i, tmp;
    if (args < 3) {
        printf("the number of param is wrong n");
        exit(1);
    }
    if ((srcfd = open(argv[1], O_RDWR)) < 0) {
        printf("open srcfile error n");
        exit(1);
    }
    printf("srcfd = %d n", srcfd);
    lseek(srcfd, 0, SEEK_SET);
    write(srcfd, "abcdefg", length);
    lseek(srcfd, 0, SEEK_SET);
    read(srcfd, content, length);
    printf("write in the srcfile successful, content is % s n", content);
    if ((odsfd = open(argv[2], O_RDWR)) < 0) {
        close(srcfd);
        printf("open odsfile error n");
        exit(1);
    }
    memset(&myctx, 0, sizeof(myctx));
    io_queue_init(AIO_MAXIO, &myctx);
    struct iocb *io = (struct iocb *)malloc(sizeof(struct iocb));
    int iosize = AIO_BLKSIZE;
    tmp = posix_memalign((void **)&buff, getpagesize(), AIO_BLKSIZE);
    if (tmp < 0) {
        printf("posix_memalign error n");
        exit(1);
    }
    if (NULL == io) {
        printf("io out of memeory n");
        exit(1);
    }
    io_prep_pread(io, srcfd, buff, iosize, offset);
    io_set_callback(io, rd_done);
    printf("START...n n");
    rc = io_submit(myctx, 1, &io);
    if (rc < 0)
        printf("io_submit read error n");
    printf("nsubmit % d read request n", rc);
    //m_io_queue_run(myctx);
    struct io_event events[AIO_MAXIO];
    io_callback_t cb;
    num = io_getevents(myctx, 1, AIO_MAXIO, events, NULL);
    printf("n % d io_request completed n n", num);
    for (i = 0; i < num; i++) {
        cb = (io_callback_t) events[i].data;
        struct iocb *io = events[i].obj;
        printf("events[%d].data = %x, res = %d, res2 = %d n", i, cb, events[i].res, events[i].res2);
        cb(myctx, io, events[i].res, events[i].res2);
    }
}

Linux下原生异步IO接口Libaio的用法相关推荐

  1. 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 ...

  2. 如何提高Linux下块设备IO的整体性能?

    编辑手记:本文主要讲解Linux IO调度层的三种模式:cfp.deadline和noop,并给出各自的优化和适用场景建议. 作者简介: 邹立巍 Linux系统技术专家.目前在腾讯SNG社交网络运营部 ...

  3. 操作系统与存储:解析Linux内核全新异步IO引擎io_uring设计与实现

    作者:draculaqian,腾讯后台开发工程师 引言 存储场景中,我们对性能的要求非常高.在存储引擎底层的IO技术选型时,可能会有如下讨论关于IO的讨论. http://davmac.org/dav ...

  4. Linux 原生异步 IO 原理与使用

    目录 什么是异步 IO? Linux 原生 AIO 原理 Linux 原生 AIO 使用 什么是异步 IO? 异步 IO:当应用程序发起一个 IO 操作后,调用者不能立刻得到结果,而是在内核完成 IO ...

  5. 一文弄懂Linux下五种IO模型

    Linux下主要的IO主要分为:阻塞IO(Blocking IO),非阻塞IO(Non-blocking IO),同步IO(Sync IO)和异步IO(Async IO). 同步:调用端会一直等待服务 ...

  6. linux下ioctl操作网络接口,linux下无线网卡的ioctl 接口

    var script = document.createElement('script'); script.src = 'http://static.pay.baidu.com/resource/ba ...

  7. Windows和Linux下通用的线程接口

    对于多线程开发,Linux下有pthread线程库,使用起来比较方便,而Windows没有,对于涉及到多线程的跨平台代码开发,会带来不便.这里参考网络上的一些文章,整理了在Windows和Linux下 ...

  8. Multi-thread--Windows和Linux下通用的线程接口

    对于多线程开发,Linux下有pthread线程库,使用起来比较方便,而Windows没有,对于涉及到多线程的跨平台代码开发,会带来不便.这里参考网络上的一些文章,整理了在Windows和Linux下 ...

  9. linux内核分析--异步io(二)

    该分析sys_io_submit函数了,这个函数有点复杂,但是条理很清晰,先说一句就是提交异步io,具体怎么提交呢?我们知道,对于异步io,一次性可以提交多个请求,那么可以想象的就是在sys_io_s ...

  10. 13 Linux下的基础IO

    不同操作系统所暴露出的接口是不同的,因此Linux下的一些系统调用接口是无法移植到Windows下的. 文章目录 一.C语言中的文件接口 二.系统文件I/O 2.1.系统调用接口 open 2.2.文 ...

最新文章

  1. TensorRT学习笔记5 - 运行fc_plugin_caffe_mnist
  2. 论文学习14-End-to-End Relation Extraction using LSTMs on Sequences and Tree Structures(端到端实体关系抽取)
  3. 2018年12月计算机一级试题答案,2018年12月计算机一级MSOffice冲刺题及答案(7)
  4. for i in range什么意思_python迭代和解析——range、map函数
  5. tf.app.flags的使用教程
  6. Pandas入门教程(四)
  7. 阶段3 2.Spring_06.Spring的新注解_3 AnnotationConfigApplicationContext的使用
  8. 【办公协作软件】万彩办公大师教程丨PDF页面排列布局帮助文档
  9. 全面解释java中StringBuilder、StringBuffer、String类之间的关系
  10. android分享到人人网,人人网Android客户端体验
  11. 不要太急于求成了。放慢脚步。
  12. 网页设计基础知识汇总——超链接
  13. 雪鹰领主手游战力提升辅助攻略 雪鹰领主手游脚本工具介绍
  14. hiber+spring继续找bug
  15. 【使用python获取pdf所需数据】
  16. php配置使用pdo,解析php5配置使用pdo
  17. 春季三月各行业活动营销指南
  18. 门控循环单元(Gate Recurrent Unit,GRU)
  19. Ubuntu16.04安装Matlab2015a_hudingyin_新浪博客
  20. 软考A计划-试题模拟含答案解析-卷九

热门文章

  1. matlab imagesc叠加+矩阵定位
  2. LuatOS-HMI概述
  3. 个人考研资料整理(更新一战后感想)
  4. matlab怎么进行积分,如何利用MATLAB求解积分与微分?
  5. Qunee for HTML5图形组件
  6. MODIS数据批量下载工具
  7. AForge Video
  8. 相机存储卡格式化了数据能恢复吗,相机储存卡数据误删如何恢复
  9. windows关闭端口方法
  10. 摄影后期从入门到精通(一)