我正在使用内核级异步I/O(即libaio.h
)。在使用struct iocb
提交io_submit
之前,我使用io_set_callback
设置了回调,该回调将函数指针粘贴在iocb->data
中。最后,我使用io_getevents
获取完成的事件并运行每个回调。
我希望能够在回调中使用一些上下文信息(例如,提交时间戳)。我可以想到的唯一方法是继续使用io_getevents
,但iocb->data
指向具有上下文和回调的结构。
还有其他类似的方法可以使用iocb->data
保证io_getevents
保持不变吗?我的理解是,还有一种方法可以使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
集成。您可以使用
aiocb
将io_set_eventfd(iocb* cb, int fd)
绑定(bind)到eventfd文件描述符。每当作业完成时,都会将eventfd加1。请注意,如果使用此机制,请务必不要从io上下文(使用
io_getevents()
)中读取比eventfd计数器所说的更多的作业,这非常重要,否则,您将在读取eventfd计数器并获得收入时引入竞争条件。工作。关于linux - 在libaio回调中正确处理上下文数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9825258/