我正在使用内核级异步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集成。

您可以使用aiocbio_set_eventfd(iocb* cb, int fd)绑定(bind)到eventfd文件描述符。每当作业完成时,都会将eventfd加1。

请注意,如果使用此机制,请务必不要从io上下文(使用io_getevents())中读取比eventfd计数器所说的更多的作业,这非常重要,否则,您将在读取eventfd计数器并获得收入时引入竞争条件。工作。

关于linux - 在libaio回调中正确处理上下文数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9825258/

10-10 08:47