Linux内核开发之异步通知与异步I/O(三)
来源:互联网 发布:软文标题 知乎 编辑:程序博客网 时间:2024/06/08 14:23
小王,听说过AIO没?外国人,就这样,总是爱简写,简写的结果是咱们都不认识了。所谓AIO就是Asynchronous Input/Output异步输入/输出,基本思想是允许进程发起很多的I/O操作,而不用阻塞或等待任何操作的完成,稍后或在接收到I/O操作完成的通知时,进程就可以检索I/O操作的结果。
“得得,你咋又跟我上起课来了呢,不是说好,今天CS吗?是不是跟我讲课特自信啊“小王抱怨到。
“啊?不是吧,为啥这样呢,那你到底听不听,别到时面试叫天天不灵叫地地不应的,别再找我哈”我气愤的说。
"唉,你都这样说了,我也只能竖起耳朵好好听听了"看着小王极不情愿的表情,我也觉得很可怜啊。
在异步非阻塞IO中,我们是可以同时发起多个传输操作。这需要每个操作都有一个唯一的上下文,这样才能在它们完成时区分到底是哪个传输操作完成了。在AIO中,
通过aiocb(AIO IO control Block)结构体进行区分,这个结构体如下:
struct aiocb {intaio_fildes;/* File descriptor */off_taio_offset;/* File offset */volatile void *aio_buf;/* Location of buffer */size_taio_nbytes;/* Length of transfer */intaio_reqprio;/* Request priority offset */struct sigeventaio_sigevent;/* Signal number and value */intaio_lio_opcode;/* Operation to be performed */};
从上边我们可以看到,这个结构体包含了有关传输的所有信息,包括数据准备的用户缓冲区。在产生IO通知时,aiocb结构就被用来唯一标识所完成的IO操作。
AIO系列API中主要有下边几个函数:
1.int aio_read(struct aiocb *aiocbp)
该函数请求对一个有效的文件描述符进行异步读操作。在请求进行排队之后会立即返回,如果执行成功,返回值就为0,错误则返回-1并设置errno的值。
2.int aio_write(struct aiocb *aiocbp)
该函数请求一个异步写操作,它会立即返回说明请求已经进行排队,成功返回0,失败返回为-1,并设置相应的error值。
3.int aio_error(struct aiocb *aiocbp)
该函数用来确定请求的状态,可以返回EINPROGRESS(说明请求尚未完成),ECANCELLED(请求被应用程序取消了),-1(说明发生了错误,具体错误原因由error记录)。
4.ssize_t aio_return(struct aiocb *aiocbp)
由于并没有阻塞在read调用上,所以我们不能立即返回这个函数的返回状态,这是就要使用这个函数了,需要注意的是只有在aio_error调用确定请求已经完成(可能
已经完成,也可能发生了错误)之后,才能调用这个函数,这个函数的返回值就相当于同步情况下read或write系统调用的返回值(所传输的字节数,如果发生错误,则返回-1)。
5.int aio_suspend(const struct aiocb *const cblist[], int n ,const struct timespec *timeout)
用户可以通过这个函数来来挂起(或阻塞)调用进程,直到异步请求完成为止,此时会产生一个信号,或者发生其他超时操作。调用者提供了一个aiocb引用列表,其中任何一个完成都会导致给函数返回。
6.int aio_cancel(int fd ,struct aiocb *aiocbp)
该函数允许用户取消对某个文件描述符执行的一个或所有的IO请求。
如果要取消一个请求,用户需提供文件描述符和aiocb引用,如果这个请求被成功取消了,则返回AIO_CANCELED,如果该请求完成了,返回AIO_NOTCANCELED.
如果要取消对某个给定文件描述符的所有请求,用户需要提供这个文件的描述符以及一个aiocbp的NULL引用,如果所有请求被成功取消了,则返回AIO_CANCELED
,只要至少有一个没被取消,这个函数就返回AIO_NOT_CANCELED.如果没有一个请求可以被取消,该函数就会返回AIO_ALLDONE.
然后,可以使用aio_error来验证每个AIO请求,如果某个请求已经被返回了,那么aio_error就返回-1,并且error会被设置为ECANCELED.
7.int lio_listio(int mode ,struct aiocb *list[], int nent ,struct sigevent *sig)
这个操作使得用户可以在一个系统调用(一次内核上下文切换中启动大量的I/O操作)。其中,mode参数可以是LIO_WAIT或LIO_NOWAIT,前者会阻塞这个调用,直到所有的IO都完成为止,在操作进行排队之后,LIO_NOWAIT就会返回,list是一个aiocb引用的列表,最大元素的个数有nent定义的。如果list的元素为NULL,lio_lis
tio()将被忽略。
光说理论也不行,是不?现在来点实际点的:
a)用户空间读例程:
#include <aio.h>..int fd, set;struct aiocb my_aiocb;fd = open("file.txt", O_RDONLY);if( fd <0 ){ perror("open");}//清零aiocb结构体bzero((char *) &my_aiocb, sizeof(struct aiocb));//为aiocb请求分配数据缓冲区my_aiocb.aio_buf = malloc(BUFSIZE + 1);if(!my_aiocb.aio_buf) perror("malloc");//初始化aiocb的成员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");while(aio_error(&my_aiocb) == EINPROGRESS);if((ret = aio_return(&my_iocb))){ // 获得异步读的返回值}else{ 读失败,分析errror}
b)用户空间异步IO aio_suspend()函数使用例程
struct aioct *cblist(MAX_LIST)//清零aioct结构链表bzero((char *)cblist, sizeof(cblist));//将一个或更多的aiocb放入aioct结构体链表cblist[0] = &my_aiocb;ret = aio_read( &my_aiocb);ret = aio_suspend( cblist, MAX_LIST, NULL);
c)用户空间异步IO lio_list()函数使用例程
struct aiocb aiocb1,aiocb2;struct aiocb *list[MAX_LIST];...//准备第一个aiocbaiocb1.aio_fildes = fd;aiocb1.aio_buf = malloc(BUFSIZE +1);aiocb1.aio_nbytes = BUFSIZE;aiocb1.aio_offset = next_offset;aiocb1.aio_lio_opcode = LIO_READ;//异步读操作...//准备多个aiocbbzero((char *)list, sizeof(list));//将aiocb填入链表list[0] = &aiocb1;list[1] = &aiocb2;...ret = lio_listio(LIO_WAIT, list, MAX_LIST, NULL); //发起大量IO操作
“涛哥,你说了这么多,好像也咋没和你说的驱动扯上关系呢”小王抱怨道。
“小王,不要急吗,我不是正打算说吗,瞧你着急性子,这样吧,你把今天的好好看看,我们下集再说”…
- Linux内核开发之异步通知与异步I/O(三)
- Linux内核开发之异步通知与异步I/O(三)
- Linux内核开发之异步通知与异步I/O《来自linux设备开发详解》
- Linux内核开发之异步通知与异步I/O(一)
- Linux内核开发之异步通知与异步I/O(二)
- Linux内核开发之异步通知与异步I/O(四)
- Linux内核开发之异步通知与异步I/O(五)
- Linux内核开发之异步通知与异步I/O(一)
- Linux内核开发之异步通知与异步I/O(二)
- Linux内核开发之异步通知与异步I/O(四)
- Linux内核开发之异步通知与异步I/O(五)
- Linux内核开发之异步通知与异步I/O(一)
- Linux内核开发之异步通知与异步I/O_fcntl
- linux设备驱动之异步通知与异步I/O
- Linux设备驱动之阻塞I/O与异步通知
- Linux设备驱动中的异步通知与异步I/O
- linux异步通知与异步I/O笔记
- Linux设备驱动中的异步通知与异步I/O
- ZooKeeper API
- 二分查找
- Java IO流学习总结
- [Oracle] enq: TX - row lock contention 优化案例
- 黑马程序员-File类文件操作
- Linux内核开发之异步通知与异步I/O(三)
- 实践敏捷估算(1)——不仅仅是估不准的问题
- 线性表中插入元素的实现,有兴趣可以看一下
- Linux内核开发之异步通知与异步I/O(四)
- Linux内核开发之异步通知与异步I/O(五)
- Cocos2d-x:整体框架源码分析以及启动过程原理(win32)
- Java集合框架官方教程(5):集合类的同步包装器/不可变包装器
- 编程问题
- QSignalMapper类处理多信号关联同一个槽的方法(1)