aio_offset 域就确定了数据在要写入的文件中的偏移量。
aio_suspend
我们可以使用 aio_suspend 函数来挂起(或阻塞)调用进程,直到异步请求完成为止,此时会产生一个信号,或者发生其他超时操作。调用者提供了一个 aiocb 引用列表,其中任何一个完成都会导致 aio_suspend 返回。 aio_suspend 的函数原型如下:
int aio_suspend( const struct aiocb *const cblist[],
int n, const struct timespec *timeout );
|
aio_suspend 的使用非常简单。我们要提供一个 aiocb 引用列表。如果任何一个完成了,这个调用就会返回 0。否则就会返回 -1,说明发生了错误。请参看清单 3。
清单 3. 使用 aio_suspend 函数阻塞异步 I/O
struct aioct *cblist[MAX_LIST]
/* Clear the list. */
bzero( (char *)cblist, sizeof(cblist) );
/* Load one or more references into the list */
cblist[0] = &my_aiocb;
ret = aio_read( &my_aiocb );
ret = aio_suspend( cblist, MAX_LIST, NULL );
|
注意,aio_suspend 的第二个参数是 cblist 中元素的个数,而不是 aiocb 引用的个数。cblist 中任何 NULL 元素都会被 aio_suspend 忽略。
如果为 aio_suspend 提供了超时,而超时情况的确发生了,那么它就会返回 -1,errno 中会包含 EAGAIN。
aio_cancel
aio_cancel 函数允许我们取消对某个文件描述符执行的一个或所有 I/O 请求。其原型如下:
int aio_cancel( int fd, struct aiocb *aiocbp );
|
要取消一个请求,我们需要提供文件描述符和 aiocb 引用。如果这个请求被成功取消了,那么这个函数就会返回 AIO_CANCELED。如果请求完成了,这个函数就会返回 AIO_NOTCANCELED。
要取消对某个给定文件描述符的所有请求,我们需要提供这个文件的描述符,以及一个对 aiocbp 的 NULL 引用。如果所有的请求都取消了,这个函数就会返回 AIO_CANCELED;如果至少有一个请求没有被取消,那么这个函数就会返回 AIO_NOT_CANCELED;如果没有一个请求可以被取消,那么这个函数就会返回 AIO_ALLDONE。我们然后可以使用 aio_error 来验证每个 AIO 请求。如果这个请求已经被取消了,那么 aio_error 就会返回 -1,并且 errno 会被设置为 ECANCELED。
lio_listio
最后,AIO 提供了一种方法使用 lio_listio API 函数同时发起多个传输。这个函数非常重要,因为这意味着我们可以在一个系统调用(一次内核上下文切换)中启动大量的 I/O 操作。从性能的角度来看,这非常重要,因此值得我们花点时间探索一下。lio_listio API 函数的原型如下:
int lio_listio( int mode, struct aiocb *list[], int nent,
struct sigevent *sig );
|
mode 参数可以是 LIO_WAIT 或 LIO_NOWAIT。LIO_WAIT 会阻塞这个调用,直到所有的 I/O 都完成为止。在操作进行排队之后,LIO_NOWAIT 就会返回。list 是一个 aiocb 引用的列表,最大元素的个数是由 nent 定义的。注意 list 的元素可以为 NULL,lio_listio 会将其忽略。sigevent 引用定义了在所有 I/O 操作都完成时产生信号的方法。
对于 lio_listio 的请求与传统的 read 或 write 请求在必须指定的操作方面稍有不同,如清单 4 所示。
清单 4. 使用 lio_listio 函数发起一系列请求
struct aiocb aiocb1, aiocb2;
struct aiocb *list[MAX_LIST];
...
/* Prepare the first aiocb */
aiocb1.aio_fildes = fd;
aiocb1.aio_buf = malloc( BUFSIZE+1 );
aiocb1.aio_nbytes = BUFSIZE;
aiocb1.aio_offset = next_offset;
aiocb1.aio_lio_opcode = LIO_READ;
...
bzero( (char *)list, sizeof(list) );
list[0] = &aiocb1;
list[1] = &aiocb2;
ret = lio_listio( LIO_WAIT, list, MAX_LIST, NULL );
|
对于读操作来说,aio_lio_opcode 域的值为 LIO_READ。对于写操作来说,我们要使用 LIO_WRITE,不过 LIO_NOP 对于不执行操作来说也是有效的。
AIO 通知
如果您对本文有任何疑问或者建议,请到讨论区发表您的意见:
>>
论坛入口 <<
上一篇:Linux 调度器内幕 下一篇:CLFS2.0原理分析
【文章评论】
【收藏本文】
【推荐好友】
【打印本文】
【我要投稿】 【论坛讨论】