Noa*_*ins 3 linux io asynchronous aio
我正在使用内核级异步 I/O(即libaio.h
)。struct iocb
在提交using之前,io_submit
我设置了回调 using 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
};
Run Code Online (Sandbox Code Playgroud)
当您发布作业时,无论一次执行一个还是批量执行,您都会提供一组指向结构的指针,这意味着它们也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
}
Run Code Online (Sandbox Code Playgroud)
如果您不想阻止 in io_getevents
,而是通过文件描述符收到通知(这样您就可以阻止 inselect()
或epoll()
,这可能更方便),我建议使用(未记录的)eventfd
集成。
您可以将 an 绑定aiocb
到 eventfd 文件描述符io_set_eventfd(iocb* cb, int fd)
。每当作业完成时,它就会将 eventfd 加一。
请注意,如果您使用此机制,请务必不要从 io 上下文(使用io_getevents()
)读取比 eventfd 计数器所说的数量更多的作业,否则在读取 eventfd 计数器并获取作业时会引入竞争条件。