3

我正在使用内核级异步 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似乎真的很缺乏。

4

1 回答 1

4

我认为典型的一种解决方案是从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到 eventfd 文件描述符io_set_eventfd(iocb* cb, int fd)。每当作业完成时,它会将 eventfd 加一。

请注意,如果您使用此机制,则永远不要从 io 上下文(with io_getevents())中读取比 eventfd 计数器所说的更多的作业,否则您会在读取 eventfd 计数器并获得作业时引入竞争条件.

于 2012-03-23T07:50:46.067 回答