Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1826506
  • 博文数量: 286
  • 博客积分: 3713
  • 博客等级: 少校
  • 技术积分: 2275
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-11 09:47
个人简介

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

文章分类

全部博文(286)

文章存档

2018年(1)

2017年(16)

2016年(9)

2015年(17)

2014年(15)

2013年(112)

2012年(116)

分类: LINUX

2013-03-06 09:51:42

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的用法,下面通过简单的例子进一步说明。
     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    }


阅读(10471) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~