我正在使用内核级异步I / O(即libaio.h).在使用io_submit提交结构iocb之前,我使用io_set_callback设置了回调,该回调将函数指针粘贴在iocb-> data中.最后,我使用io_getevents获得完成的事件并运行每个回调.
我希望能够在回调中使用一些上下文信息(例如,提交时间戳).我可以想到的唯一方法是继续使用io_getevents,但是让iocb-> data指向具有上下文和回调的结构.
还有其他方法可以执行这样的操作吗?在使用io_getevents时,是否保证iocb-> data不受影响?我的理解是,还有另外一种方法,libaio将通过该方法自动运行回调,如果iocb-> data没有指向函数,这将是一个问题.
这里的任何澄清都很好.似乎确实缺少关于libaio的文档.
解决方法:
我想象的典型解决方案是从iocb“派生”,然后将从io_getevents()返回的指针转换为结构.像这样:
struct my_iocb {
iocb cb;
void* userdata;
// ... anything else
};
在发布作业时,无论一次执行还是批量执行,都将提供一个指向iocb结构的指针数组,这意味着它们也可能指向my_iocb.
当您从io_getevents()取回通知时,只需将io_event :: obj指针强制转换为您自己的类型:
io_event events[512];
int num_events = io_getevents(ioctx, 1, 512, events, NULL);
for (int i = 0; i < num_events; ++i) {
my_iocb* job = (my_iocb*)events[i].obj;
// .. do stuff with job
}
如果您不想在io_getevents中进行阻止,而是通过文件描述符进行通知(以便您可以在select()或epoll()中进行阻止,这可能会更方便),我建议您使用(未记录)eventfd积分.
您可以使用io_set_eventfd(iocb * cb,int fd)将aiocb绑定到eventfd文件描述符.每当作业完成时,都会将eventfd加1.
请注意,如果使用此机制,请务必不要从io上下文(使用io_getevents())读取比eventfd计数器所说的更多的作业,否则,从读取eventfd计数器和获得工作.