Chinaunix首页 | 论坛 | 博客
  • 博客访问: 822703
  • 博文数量: 96
  • 博客积分: 1553
  • 博客等级: 上尉
  • 技术积分: 1871
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-25 14:50
个人简介

专注点,细心点,耐心点 知行合一

文章分类

全部博文(96)

文章存档

2018年(1)

2014年(4)

2013年(31)

2012年(56)

2011年(4)

分类: C/C++

2014-12-27 11:12:45


点击(此处)折叠或打开

  1. #define _GNU_SOURCE
  2. #define __STDC_FORMAT_MACROS
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <libaio.h>
  6. #include <sys/eventfd.h>
  7. #include <sys/epoll.h>
  8. #include <stdlib.h>
  9. #include <sys/types.h>
  10. #include <unistd.h>
  11. #include <stdint.h>
  12. #include <sys/stat.h>
  13. #include <fcntl.h>
  14. #include <inttypes.h>
  15. #define TEST_FILE "aio_test_file"
  16. #define TEST_FILE_SIZE (127 * 1024)
  17. #define NUM_EVENTS 128
  18. #define ALIGN_SIZE 512
  19. #define RD_WR_SIZE 1024
  20. struct custom_iocb
  21. {
  22.     struct iocb iocb;
  23.     int nth_request;
  24. };
  25. void aio_callback(io_context_t ctx, struct iocb *iocb, long res, long res2)
  26. {
  27.     struct custom_iocb *iocbp = (struct custom_iocb *)iocb;
  28.     printf("nth_request: %d, request_type: %s, offset: %lld, length: %lu, res: %ld, res2: %ld\n",
  29.             iocbp->nth_request, (iocb->aio_lio_opcode == IO_CMD_PREAD) ? "READ" : "WRITE",
  30.             iocb->u.c.offset, iocb->u.c.nbytes, res, res2);
  31. }
  32. int main(int argc, char *argv[])
  33. {
  34.     int efd, fd, epfd;
  35.     io_context_t ctx;
  36.     struct timespec tms;
  37.     struct io_event events[NUM_EVENTS];
  38.     struct custom_iocb iocbs[NUM_EVENTS];
  39.     struct iocb *iocbps[NUM_EVENTS];
  40.     struct custom_iocb *iocbp;
  41.     int i, j, r;
  42.     void *buf;
  43.     struct epoll_event epevent;
  44.     efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  45.     if (efd == -1) {
  46.         perror("eventfd");
  47.         return 2;
  48.     }
  49.     fd = open(TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644);
  50.     if (fd == -1) {
  51.         perror("open");
  52.         return 3;
  53.     }
  54.     ftruncate(fd, TEST_FILE_SIZE);
  55.     
  56.     ctx = 0;
  57.     if (io_setup(8192, &ctx)) {
  58.         perror("io_setup");
  59.         return 4;
  60.     }
  61.     if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) {
  62.         perror("posix_memalign");
  63.         return 5;
  64.     }
  65.     printf("buf: %p\n", buf);
  66.     for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) {
  67.         iocbps[i] = &iocbp->iocb;
  68.         io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
  69.         io_set_eventfd(&iocbp->iocb, efd);
  70.         io_set_callback(&iocbp->iocb, aio_callback);
  71.         iocbp->nth_request = i + 1;
  72.     }
  73.     if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) {
  74.         perror("io_submit");
  75.         return 6;
  76.     }
  77.     epfd = epoll_create(1);
  78.     if (epfd == -1) {
  79.         perror("epoll_create");
  80.         return 7;
  81.     }
  82.     epevent.events = EPOLLIN | EPOLLET;
  83.     epevent.data.ptr = NULL;
  84.     if (epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent)) {
  85.         perror("epoll_ctl");
  86.         return 8;
  87.     }
  88.     i = 0;
  89.     while (i < NUM_EVENTS) {
  90.         uint64_t finished_aio;
  91.         if (epoll_wait(epfd, &epevent, 1, -1) != 1) {
  92.             perror("epoll_wait");
  93.             return 9;
  94.         }
  95.         if (read(efd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio)) {
  96.             perror("read");
  97.             return 10;
  98.         }
  99.         printf("finished io number: %"PRIu64"\n", finished_aio);
  100.     
  101.         while (finished_aio > 0) {
  102.             tms.tv_sec = 0;
  103.             tms.tv_nsec = 0;
  104.             r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms);
  105.             if (r > 0) {
  106.                 for (j = 0; j < r; ++j) {
  107.                     ((io_callback_t)(events[j].data))(ctx, events[j].obj, events[j].res, events[j].res2);
  108.                 }
  109.                 i += r;
  110.                 finished_aio -= r;
  111.             }
  112.         }
  113.     }
  114.     
  115.     close(epfd);
  116.     free(buf);
  117.     io_destroy(ctx);
  118.     close(fd);
  119.     close(efd);
  120.     remove(TEST_FILE);
  121.     return 0;
  122. }

说明:
1. 在centos 6.2 (libaio-devel 0.3.107-10) 上运行通过
2. struct io_event中的res字段表示读到的字节数或者一个负数错误码。在后一种情况下,-res表示对应的
   errno。res2字段为0表示成功,否则失败
3. iocb在aio请求执行过程中必须是valid的
4. 在上面的程序中,通过扩展iocb结构来保存额外的信息(nth_request),并使用iocb.data
   来保存回调函数的地址。如果回调函数是固定的,那么也可以使用iocb.data来保存额外信息。
阅读(1087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~