AIO in C
AIO, 即异步非阻塞I/O,允许了包括I/O与处理计算的重叠。在大量并发任务下,理论上可以提高相应的处理计算性能。在此简单记录一下C语言中的AIO,方便后续有需要时候查询。
在Unix中,所有的I/O本质上都是对文件描述符的一种操作。在AIO中对应的文件描述符为一个叫aiocb(AIO I/O Control Block)的结构体。这个结构体存储了关于当下传输的所有信息,包括一个用户端的数据缓存。当I/O完成或者产生异常时,aiocb可以用来唯一的标识这一个已经停止的I/O操作。aiocb的结构如下:
1 | struct aiocb { |
aiocb相当于我们在标准I/O中的文件描述符,或者相当于网络I/O中的Socket。可以通过如下AIO API对一个aiocb进行操作:
API | 介绍 |
---|---|
aio_read | 异步读操作 |
aio_error | 检验异步请求状态 |
aio_return | 获得一个已结束的I/O 的返回值 |
aio_write | 异步写操作 |
aio_suspend | 挂起当前进程,阻塞等待直到有一个或者多个异步请求结束(或者异常) |
aio_cancel | 取消一个异步请求 |
lio_listio | 初始化一系列异步I/O操作 |
如下是一个简单的AIO调用:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
int main(int argc, char **argv)
{
int fd, ret;
struct aiocb read_aiocb;
fd = open("test", O_RDONLY);
if (fd < 0)
{
perror("open");
}
/* Zero out the aiocb structure (recommended) */
bzero((char *)&read_aiocb, sizeof(struct aiocb));
read_aiocb.aio_fildes = fd;
read_aiocb.aio_buf = malloc(100);
read_aiocb.aio_nbytes = 99;
read_aiocb.aio_offset = 0;
printf("calling aio...\n");
if (aio_read(&read_aiocb) < 0)
{
perror("aio_read");
}
printf("do something else...\n");
printf("use aio_suspend to block reading...\n");
struct aiocb *cblist[1];
bzero((char *)cblist, sizeof(cblist));
cblist[0] = &read_aiocb;
ret = aio_suspend(cblist, 1, NULL);
printf("get: %s\n", read_aiocb.aio_buf);
return 0;
}
同时,AIO也提供了通过信号以及通过回调的方式进行异步通知的方法。