异步IO接口Libaio的用法http://blog.chinaunix.net/uid-16979052-id-3509393.html

 
  •     
  •     
  •    
    • 博客访问: 562014
    • 博文数量: 269
    • 博客积分: 3713
    • 博客等级: 少校
    • 技术积分: 2099
    • 用 户 组: 普通用户
    • 注册时间: 2012-01-11 09:47
    个人简介

    http://blog.chinaunix.net/uid/16979052.html

    文章分类

    全部博文(269)

    文章存档

    2015年(13)

    2014年(16)

    2013年(119)

    2012年(121)

    微信关注

    IT168企业级官微



    微信号:IT168qiye



    系统架构师大会



    微信号:SACC2013

    订阅
    热词专题
      友情链接
        异步IO接口Libaio的用法  2013-03-06 09:51:42

      分类: LINUX

      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 *eve nts, 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的用法,下面通过简单的例子进一步说明。
           1    #include 
           2    #include 
           3    #include 
           4    #include 
           5    #include 
           6    #include 
           7    int srcfd = -1;
           8    int odsfd = -1;
           9    #define AIO_BLKSIZE  1024
          10    #define AIO_MAXIO 64
          11    static void wr_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
          12    {
          13        if (res2 != 0)
          14        {
          15            printf("aio write error n");
          16        }
          17        if (res != iocb->u.c.nbytes)
          18        {
          19            printf("write missed bytes expect %d got %d n", iocb->u.c.nbytes, res);
          20            exit(1);
          21        }
          22        free(iocb->u.c.buf);
          23        free(iocb);
          24    }
          25    static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
          26    {
          27        int iosize = iocb->u.c.nbytes;
          28        char *buf = (char *)iocb->u.c.buf;
          29        off_t offset = iocb->u.c.offset;
          30        int tmp;
          31        char *wrbuff = NULL;
          32        if (res2 != 0)
          33        {
          34            printf("aio read n");
          35        }
          36        if (res != iosize)
          37        {
          38            printf("read missing bytes expect % d got % d", iocb->u.c.nbytes, res);
          39            exit(1);
          40        }
          41        tmp = posix_memalign((void **)&wrbuff, getpagesize(), AIO_BLKSIZE);
          42        if (tmp < 0)
          43        {
          44            printf("posix_memalign222 n");
          45            exit(1);
          46        }
          47        snprintf(wrbuff, iosize + 1, "%s", buf);
          48        printf("wrbuff - len = %d:%s n", strlen(wrbuff), wrbuff);
          49        printf("wrbuff_len = %d n", strlen(wrbuff));
          50        free(buf);
          51        io_prep_pwrite(iocb, odsfd, wrbuff, iosize, offset);
          52        io_set_callback(iocb, wr_done);
          53        if (1 != (res = io_submit(ctx, 1, &iocb)))
          54            printf("io_submit write error n");
          55        printf("nsubmit % d write request n", res);
          56    }
          57    void main(int args, void *argv[])
          58    {
          59        int length = sizeof("abcdefg");
          60        char *content = (char *)malloc(length);
          61        io_context_t myctx;
          62        int rc;
          63        char *buff = NULL;
          64        int offset = 0;
          65        int num, i, tmp;
          66        if (args < 3)
          67        {
          68            printf("the number of param is wrong n");
          69            exit(1);
          70        }
          71        if ((srcfd = open(argv[1], O_RDWR)) < 0)
          72        {
          73            printf("open srcfile error n");
          74            exit(1);
          75        }
          76        printf("srcfd = %d n", srcfd);
          77        lseek(srcfd, 0, SEEK_SET);
          78        write(srcfd, "abcdefg", length);
          79        lseek(srcfd, 0, SEEK_SET);
          80        read(srcfd, content, length);
          81        printf("write in the srcfile successful, content is % s n", content);
          82        if ((odsfd = open(argv[2], O_RDWR)) < 0)
          83        {
          84            close(srcfd);
          85            printf("open odsfile error n");
          86            exit(1);
          87        }
          88        memset(&myctx, 0, sizeof(myctx));
          89        io_queue_init(AIO_MAXIO, &myctx);
          90        struct iocb *io = (struct iocb *)malloc(sizeof(struct iocb));
          91        int iosize = AIO_BLKSIZE;
          92        tmp = posix_memalign((void **)&buff, getpagesize(), AIO_BLKSIZE);
          93        if (tmp < 0)
          94        {
          95            printf("posix_memalign error n");
          96            exit(1);
          97        }
          98        if (NULL == io)
          99        {
         100            printf("io out of memeory n");
         101            exit(1);
         102        }
         103        io_prep_pread(io, srcfd, buff, iosize, offset);
         104        io_set_callback(io, rd_done);
         105        printf("START...n n");
         106        rc = io_submit(myctx, 1, &io);
         107        if (rc < 0)
         108            printf("io_submit read error n");
         109        printf("nsubmit % d read request n", rc);
         110        //m_io_queue_run(myctx);
         111        struct io_event events[AIO_MAXIO];
         112        io_callback_t cb;
         113        num = io_getevents(myctx, 1, AIO_MAXIO, events, NULL);
         114        printf("n % d io_request completed n n", num);
         115        for (i = 0; i < num; i++)
         116        {
         117            cb = (io_callback_t) events[i].data;
         118            struct iocb *io = events[i].obj;
         119            printf("events[%d].data = %x, res = %d, res2 = %d n", i, cb, events[i].res, events[i].res2);
         120            cb(myctx, io, events[i].res, events[i].res2);
         121        }
         122    }


      阅读(3209) | 评论(0) | 转发(2) |
      给主人留下些什么吧!~~
      评论热议
      请登录后评论。

      登录 注册


      id="cproIframe_u1625692_1" width="468" height="60" src="http://pos.baidu.com/acom?adn=2&at=225&aurl=&cad=1&ccd=24&cec=UTF-8&cfv=18&ch=0&col=zh-CN&conBW=0&conOP=1&cpa=1&dai=1&dis=0&layout_filter=image&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DDxbu1PWoSjWWIfqlXLTvqp_5F3jVhPVjJcCh0aDEVj8QKchuOiygkHstZ1nza8RpxwAcJeAoa6p6N7GIgxK5p_%26wd%3D%26eqid%3Dd47f7b5f000167f50000000255db1df0&ltu=http%3A%2F%2Fblog.chinaunix.net%2Fuid-16979052-id-3509393.html&lu_161=6&lunum=6&n=01084029_cpr&pcs=1274x682&pis=10000x10000&ps=6429x305&psr=1366x768&pss=1274x6429&qn=a44260dc778c4c66&rad=&rsi0=468&rsi1=60&rsi5=4&rss0=%23FFFFFF&rss1=%23FFFFFF&rss2=%230000ff&rss3=%23444444&rss4=%23008000&rss5=&rss6=%23e10900&rss7=&scale=&skin=tabcloud_skin_3&stid=5&td_id=1625692&titFF=%E5%AE%8B%E4%BD%93&titFS=12&titTA=left&tn=text_default_468_60&tpr=1440423429526&ts=1&version=2.0&xuanting=0&dtm=BAIDU_DUP2_SETJSONADSLOT&dc=2&di=u1625692&ti=%E5%BC%82%E6%AD%A5IO%E6%8E%A5%E5%8F%A3Libaio%E7%9A%84%E7%94%A8%E6%B3%95-sometimeixpub-ChinaUnix%E5%8D%9A%E5%AE%A2&tt=1440423429470.59.104.112" align="center,center" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="word-wrap: break-word;">
      id="cproIframe_u1625694_2" width="468" height="60" src="http://pos.baidu.com/acom?adn=2&at=71&aurl=&cad=1&ccd=24&cec=UTF-8&cfv=18&ch=0&col=zh-CN&conOP=0&cpa=1&dai=2&dis=0&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DDxbu1PWoSjWWIfqlXLTvqp_5F3jVhPVjJcCh0aDEVj8QKchuOiygkHstZ1nza8RpxwAcJeAoa6p6N7GIgxK5p_%26wd%3D%26eqid%3Dd47f7b5f000167f50000000255db1df0&ltu=http%3A%2F%2Fblog.chinaunix.net%2Fuid-16979052-id-3509393.html&lunum=6&n=01084029_cpr&pcs=1274x682&pis=10000x10000&ps=6429x245&psr=1366x768&pss=1274x6489&qn=0df40248e460c636&rad=&rsi0=468&rsi1=60&rsi5=4&rss0=%23FFFFFF&rss1=%23FFFFFF&rss2=%230000FF&rss3=%23444444&rss4=%23008000&rss5=&rss6=%23e10900&rss7=&scale=&skin=&td_id=1625694&tn=text_default_468_60&tpr=1440423429526&ts=1&version=2.0&xuanting=0&dtm=BAIDU_DUP2_SETJSONADSLOT&dc=2&di=u1625694&ti=%E5%BC%82%E6%AD%A5IO%E6%8E%A5%E5%8F%A3Libaio%E7%9A%84%E7%94%A8%E6%B3%95-sometimeixpub-ChinaUnix%E5%8D%9A%E5%AE%A2&tt=1440423429470.167.199.200" align="center,center" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="word-wrap: break-word;">
      • 0
        点赞
      • 0
        收藏
        觉得还不错? 一键收藏
      • 0
        评论

      “相关推荐”对你有帮助么?

      • 非常没帮助
      • 没帮助
      • 一般
      • 有帮助
      • 非常有帮助
      提交
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值