正确处理libaio回调中的上下文数据?

时间:2012-03-22 15:20:12

标签: linux asynchronous io aio

我正在使用内核级异步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上的文档似乎确实缺乏。

1 个答案:

答案 0 :(得分:4)

我认为一种典型的解决方案是从iocb“派生”,然后将从io_getevents()返回的指针转换为结构。像这样:

struct my_iocb {
    iocb cb;
    void* userdata;
    // ... anything else
};

当您发布作业时,无论是一次一个还是批处理,您都会向iocb结构提供一系列指针,这意味着它们可能指向{ {1}}也是。

当您从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_geteventsselect(),这可能会更方便),我建议使用(未记录的)epoll()集成。

您可以使用eventfdaiocb绑定到eventfd文件描述符。只要作业完成,它就会将eventfd递增1。

注意,如果你使用这种机制,永远不要从io上下文(使用io_set_eventfd(iocb* cb, int fd))读取比eventfd计数器所说的更多的作业非常重要,否则你会引入竞争条件。阅读eventfd计数器并收获工作。