qemu io介绍(四)
Qemu AIO:
struct LinuxAioState { AioContext *aio_context; /* 在event_notifier_init中初始化,第一个参数是允许的最大的异步IO的个数 */ io_context_t ctx; /* 这个可以是eventfd或是pipe两种形式。只是对这两种形式的一个简单封装。在event_notifier_init中初始化 */ EventNotifier e; /* io queue for submit at batch */ LaioQueue io_q; /* I/O completion processing */ QEMUBH *completion_bh; struct io_event events[MAX_EVENTS]; int event_idx; int event_max; /* 把iocb结构挂载这个链表上。 并非每一次IO都要触发submit,aio_do_submi这里只是一个 生产者,而ioq_submit是消费者? */ }; 读写数据的调用流程 bdrv_driver_pwritev ------ raw_co_prw | ------> aio_get_linux_aio | | | | ------> laio_init | | | -----> event_notifier_init(创建eventfd) | | -----> laio_attach_aio_context (把eventfd加入到epoll中,并把eventfd与qemu_laio_completion_cb关联起来。等下该eventfd有数据了就使用这个回调处理) | | -------> laio_co_submit (老版本没有启用AIO,所以不会走到这里,走的是线程池方式) | | | | ------> laio_do_submit | | | | | | ------> io_prep_pwritev(拼装iocb,用于aio) | | | | | | ------> io_set_eventfd(把event fd放到iocb中。等下发给iocb内核,内核做完了以后IO,然后通过eventfd_write,这样用户态便能通过read读取到结果了) | | | | | | ------> ioq_submit(最后调用io_submit把多个iocb一起发给内核) | | | | ------> qemu_coroutine_yield(为什么这里需要yield呢? 因为laio_do_submit函数的返回值并非此次IO的结果。所以它必须等到内核通知此次IO结果。qemu_laio_process_completion中会填充此次IO的结果,并调用qemu_coroutine_enter重新跳转到这里执行。这里就退到该协程的调用者处。 ) 也就是说使用了AIO以后就没有线程池了,只有再flush的时候才会使用到线程池 读写完成的调用流程 qemu_laio_completion_cb | | ------> event_notifier_test_and_clear(使用read清除掉eventfd里面的数据) | | ------> io_getevents(获取io结果) | | ------> qemu_laio_process_completion(处理IO结果) | | ------> qemu_coroutine_enter(回到 laio_co_submit处继续执行) ioq_submit的结果qemu已经在qemu_laio_process_completion中处理了,但并不代表它真正地写入到了物理磁盘,它其实只是写到磁盘的缓存中(打开文件的时候传入的是O_DIRECT;如果是O_SYNC的话就不用sync了)。 因此还需要把数据flush到磁盘中。那能否再打开文件的时候使用O_SYNC/O_DSYNC让它直接写入到磁盘呢。反正已经是异步的了,我们不应该再来一次flush系统调用带来的上下文切换的开销 bdrv_driver_pwritev | ------> bdrv_co_flush | | ------> raw_aio_flush | | | | | | ------> paio_submit | | | | | | ------> thread_pool_submit_aio | | | | | | ------> spawn_thread 没有idle thread的时候才会去创建一个新的aio线程,aio线程会调用aio_worker -> handle_aiocb_flush | | ------> qemu_coroutine_yield (回退到其调用者) bdrv_co_io_em_complete 重新enter到哪里去了呢? qemu_bh_schedule机制 http://www.kuqin.com/linux/20120908/330333.html


浙公网安备 33010602011771号