关于事件驱动的学习一 异步IO aio

本文介绍了AIO接口的基本概念,详细解析了aio.h文件中aiocb结构的各个字段,并通过两个实例展示了如何使用AIO进行异步读取操作。

先查看下/usr/include/aio.h中aiocb的定义

/* Asynchronous I/O control block.  */
struct aiocb
{
  int aio_fildes;                    /* File desriptor.  */                        涉及到的文件句柄,用户填写
  int aio_lio_opcode;           /* Operation to be performed.  */   执行操作,此位aio_read()会填写
  int aio_reqprio;                 /* Request priority offset.  */          优先权等级
  volatile void *aio_buf;       /* Location of buffer.  */                 buffer位置,用户填写
  size_t aio_nbytes;            /* Length of transfer.  */                 buffer长度,用户填写
  struct sigevent aio_sigevent; /* Signal number and value.  */  可以定义信号和call back的过程

  /* Internal members.  */
  struct aiocb *__next_prio;
  int __abs_prio;
  int __policy;
  int __error_code;
  __ssize_t __return_value;

#ifndef __USE_FILE_OFFSET64
  __off_t aio_offset;           /* File offset.  */                              操作的文件偏移
  char __pad[sizeof (__off64_t) - sizeof (__off_t)];
#else
  __off64_t aio_offset;         /* File offset.  */
#endif
  char __unused[32];
};

 

直接上了一个例子,学习下aio接口.

在必须验证每次读操作的结果的要求下,这个例子给出了两种方案。

第一种方案是:wait_aio,即执行了aio_read()后,循环检查aio_return返回,这样的方式相比阻塞型的read()没有多少优势

第二种方案是:call_back,即执行aio_read()的同时,定义该操作响应信号和回调函数。而程序可以继续执行下去。当本次read()操作有结果时,自动执行call_back_handler函数。 (推荐)

#include <stdio.h>
#include <unistd.h>
#include <aio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define MAXBUF 256
#define BUFSIZE 20

struct aiocb my_aiocb;
int wait_aio(int fd)
{
        int ret;
        bzero((char *) &my_aiocb,sizeof(struct aiocb));
        my_aiocb.aio_buf = malloc(BUFSIZE+1);
        if (!my_aiocb.aio_buf) {
                perror("malloc");
        }
        my_aiocb.aio_fildes = fd;
        my_aiocb.aio_nbytes = BUFSIZE;
        my_aiocb.aio_offset = 0;

        异步读文件
        ret = aio_read(&my_aiocb);
        if ( ret < 0 ) {
                perror("aio read");
        }

        如果正在读文件,一直循环等待,和同步io的效果差不多

        while (aio_return(&my_aiocb) == EINPROGRESS);
        if ( (ret=aio_return(&my_aiocb)) > 0 ) {
                printf("%s",my_aiocb.aio_buf);
        }
        else {
                perror("aio read");
        }
}

回调函数,把buffer的内容打印出来

int call_back_handler(sigval_t sigval)
{
        struct aiocb *req;
        req = (struct aiocb*)sigval.sival_ptr;
        printf("call back handler/n");
        printf("%s",req->aio_buf);
}
int call_back(int fd)
{
        int ret;
        bzero((char *) &my_aiocb,sizeof(struct aiocb));
        my_aiocb.aio_buf = malloc(BUFSIZE+1);
        my_aiocb.aio_fildes = fd;
        my_aiocb.aio_nbytes = BUFSIZE;
       my_aiocb.aio_offset = 0;
        设置读写完成后事件的通知方式

        可以使用回调函数,和信号,这里使用回调函数方式

        my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
        my_aiocb.aio_sigevent.sigev_notify_function = call_back_handler;
        my_aiocb.aio_sigevent.sigev_notify_attributes = NULL;
        my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
        printf("aio_read/n");
        ret = aio_read(&my_aiocb);
        if ( ret < 0 ) {
                perror("aio read");
        }
}

int main(int argc,char** argv)
{
        char filename[MAXBUF];
        int fd;
        // strcpy(argv[1],filename);
        fd=open("test.txt",O_RDONLY);
        if ( fd < 0 ) {
                return -1;
        }

        调用等待方式

        wait_aio(fd);

        调用回调函数方式
        call_back(fd);
}

程序在编译时需要runtime库支持,不知道这个库是否支持嵌入式平台,

gcc -o test_aio test_aio.o -lrt

 

通过上述的例子,应该明白unix中aio是如何使用的了。call_back方式比较方便,程序不用关注IO操作的返回情况。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值