126-POSIX 异步IO(批量请求)
原创
©著作权归作者所有:来自51CTO博客作者mb63083a7dd962a的原创作品,请联系作者获取转载授权,否则将追究法律责任
POSIX 提供了函数 lio_listio 可以让我们一次性发起多个异步 IO 请求。
1. lio_listio
(1) 函数原型
int lio_listio(int mode, struct aiocb *const aiocb_list[], int nitems, struct
(2) 函数参数
mode 有两个可选值:LIO_WAIT 和 LIO_NOWAIT.
值
| 含义
|
LIO_WAIT
| lio_listio 会阻塞,直到所有的异步 IO 请求完成。此时参数 sevp 被忽略掉
|
LIO_NOWAIT
| lio_listio 会立即返回,当所有异步 IO 请求完成后,会进行异步通知,通知的方式由参数 sevp 指定,该参数可以为 NULL,表示不需要异步通知。通知方式我们在下一讲就会说了。
|
struct aiocb {
/* 下面所有字段依赖于具体实现 */
int aio_fildes; /* 文件描述符 */
off_t aio_offset; /* 文件偏移 */
volatile void *aio_buf; /* 缓冲区地址 */
size_t aio_nbytes; /* 传输的数据长度 */
int aio_reqprio; /* 请求优先级 */
struct sigevent aio_sigevent; /* 通知方法 */
int aio_lio_opcode; /* 仅被 lio_listio() 函数使用 */
/* Various implementation-internal fields not shown */
aiocb_list 就是 aiocb 结构体指针的数组,nitems 参数表示数组的大小。在使用 lio_listio 函数时,需要将 aiocb 中的 aio_lio_opcode 成员赋值,所以到这里,我们又学习到了一个新的成员。该成员告诉内核发起的是何中异步 IO 操作。aio_lio_opcode 的值可以为下面这些:
值
| 含义
|
LIO_READ
| 发起异步读操作
|
LIO_WRITE
| 发起异步写操作
|
LIO_NOP
| 表示忽略掉该 aiocb
|
还有最后一个参数,这里我们先不考虑它,在使用 lio_listio 函数的时候,将 sevp 设置为 NULL 就行了。
2. 实验
程序 my_aio_lio 修改了前面的代码,将 aio_read 函数替换成了 lio_listio 函数发起异步读请求。程序中并没有演示同时发起多个请求,只是发起了一个。实际上,一个你会了,多个也没什么问题,无非就是给数组赋几个值而已。
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <aio.h>
#include <strings.h>
#include <errno.h>
#define ERR_EXIT(msg) do { perror(msg); exit(1); } while(0)
int main() {
int fd, ret;
char buf[64];
struct aiocb my_aiocb;
bzero((char*)&my_aiocb, sizeof(struct aiocb));
my_aiocb.aio_buf = buf;
my_aiocb.aio_fildes = STDIN_FILENO;
my_aiocb.aio_nbytes = 64;
my_aiocb.aio_offset = 0;
// 注意这里多了一个成员的赋值,aio_lio_opcode 成员是专门给 lio_listio 函数用的。
my_aiocb.aio_lio_opcode = LIO_READ;
// 定义一个大小为 5 的数组,多大无所谓了,看你需求了。
struct aiocb* aio_list[5] = { NULL };
// 将你想发起的请求的控制块放到数组里,放哪个位置都行。这里我只发起了一个读操作。
aio_list[3] = &my_aiocb;
// 调用 lio_listio 发起读请求
ret = lio_listio(LIO_NOWAIT, aio_list, 5, NULL);
while(aio_error(&my_aiocb) == EINPROGRESS) {
write(STDOUT_FILENO, ".", 1);
sleep(1);
}
printf("content: %s\n", buf);
return 0;
}
$ gcc my_aio_lio.c -o my_aio_lio -lrt
$ ./my_aio_lio
图1 运行结果
程序启动后,在屏幕上开始打点,不用管它,直接输入 hello 然后回车。
3. 总结