2012-03-22 18 views
3

我正在使用内核级别的异步I/O(即libaio.h)。在使用io_submit提交struct iocb之前,我使用io_set_callback设置了回调函数,它在iocb->data中粘贴了一个函数指针。最后,我使用io_getevents获得完成的事件并运行每个回调。正确处理libaio回调中的上下文数据?

我希望能够在回调中使用一些上下文信息(例如提交时间戳)。我能想到这样做的唯一方法是继续使用io_getevents,但iocb->data指向带有上下文和回调的结构。

有没有其他方法可以做这样的事情,并且iocb->data保证在使用io_getevents时保持不变?我的理解是,libaio会自动运行回调,如果iocb->data未指向某个函数,则会出现问题。

在这里的任何澄清将很好。关于libaio的文档似乎真的很缺乏。

回答

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集成。

您可以使用io_set_eventfd(iocb* cb, int fd)aiocb绑定到eventfd文件描述符。每当作业完成时,它会将eventfd递增1。

请注意,如果您使用此机制,从不会从io上下文(与io_getevents())读取更多的作业,这比eventfd计数器所说的要多,否则当您读取eventfd时会引入竞争条件反击并收获工作。

+0

是!昨晚一起磕磕绊绊。你的答案肯定会填补手册页中缺少的一些空白! – 2012-03-23 15:31:15