目前oracle公布的异步IO的实现与glibc的结构体有一些类似,只不过没有多线程,而是直接调用了libaio中的函数
/*
* we always use a 64bit off_t when communicating
* with userland. its up to libraries to do the
* proper padding and aio_error abstraction
*
* FIXME: this must change from glibc's definition
* as we do *not* use the sigevent structure which
* is big and bloated.
*/
struct aiocb64 {
int aio_fildes; /* File desriptor. */
short aio_lio_opcode; /* Operation to be performed. */
short aio_reqprio; /* Request priority offset. */
void *aio_buf; /* Location of buffer. */
size_t aio_nbytes; /* Length of transfer. */
loff_t aio_offset; /* File offset. */
/* these are internal to the kernel/libc. */
long __aio_key; // kernel sets this to -1 if completed 存的是执行的状态
// otherwise >= 0 (the request#)
void * __aio_data; // pointer to be returned in event's data 指向_AIORequest
int __error_code;
};
这就是存放数据的结构
/*
* Structures
*/
struct _AIORequest
{
struct iocb iocb; /* Control block sent to kernel */
struct aiocb64 *aiocb; /* User's control block */
AIORequest *next; /* Next in request list */
AIORequest *prev; /* Previous in request list next,prev是构成双向链表,连入_AIORequestQueue那四个List之 中
的一个*/
};
struct _AIORequestQueue
{
pid_t pid; /* Current PID */
io_context_t ctxt; /* Kernel IO context */
unsigned long max_requests; /* Maxinum number of requests */
AIORequest *requests; /* Allocated requests */
AIORequest *complete; /* List of complete requests */
AIORequest *current; /* List of outstanding requests */
AIORequest *free; /* List of free requests */
};
/* Global for the library */
static AIORequestQueue *r_queue = NULL;
全局变量,初始分配固定大小的_AIORequest,连入_AIORequestQueue->free
int aio_read64(struct aiocb64 *aiocbp)
int aio_write64(struct aiocb64 *aiocbp)
这两个函数把数据放入r_queue 里面,之后调用io_submit;当返回时是不知道是否执行成功的
static long aior_get_events(struct timespec *timeout)
最终还是调用io_getevents,返回后,修改_AIORequest->aiocb->__error_code 和 _AIORequest->aiocb->__aio_key 的状态
int aio_error64(struct aiocb64 *aiocbp)
ssize_t aio_return64(struct aiocb64 *aiocbp)
还是根据aiocb64 ->__aio_key的状态来确定返回结果,并决定是否需要调用aior_get_events来获取最新的状态
int aio_suspend64(const struct aiocb64 * const list[], int nent, const struct timespec *timeout)
int aio_reap64(struct timespec *timeout, int waitfor, struct aiocb *out_list[], int listsize, int *completed_count)
里面都有
int done = 0;
while (done == 0)
{
...
ret = aior_get_events(timeout);
...
}
这样的轮循操作,其实也是通过这种方式来获得执行结果的
总的来说,libaio-oracle,是对libaio的又一层简单封装,多了一个全局变量_AIORequestQueue *r_queue ,通过它可方便批量io_submit,和glibc的区别,一是,还没有实现执行完信号量的通知,只能通过轮循获得最终状态;二是,没有多线程分别对不同的文件进行处理,而是把所有的执行,全局提交给了操作系统的底层实现,由操作系统来接手。