我正在使用内核级异步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
上的文档似乎确实缺乏。
答案 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_getevents
或select()
,这可能会更方便),我建议使用(未记录的)epoll()
集成。
您可以使用eventfd
将aiocb
绑定到eventfd文件描述符。只要作业完成,它就会将eventfd递增1。
注意,如果你使用这种机制,永远不要从io上下文(使用io_set_eventfd(iocb* cb, int fd)
)读取比eventfd计数器所说的更多的作业非常重要,否则你会引入竞争条件。阅读eventfd计数器并收获工作。