linux異步IO:io_uring

爲了改善posix aio目前存在的問題,新的異步IO驅動:io_uring如何解決了posix aio的問題。圍繞這個問題,本文首先介紹了異步IO的概念,然後介紹了posix aio存在的問題,最後根據io_uring的源碼分析io_uring爲什麼比posix aio優異。

同步IO和異步IO

posix定義如下:

同步IO:導致請求進程阻塞,知道IO操作完成。
異步IO:不導致請求進程阻塞。

下圖詳細描繪了五種不同的I/O模型。I/O操作被看成兩個部分:等待數據和拷貝數據到用戶空間。

  • 阻塞式I/O:第一階段和第二階段均阻塞;
  • 非阻塞式I/O:第一階段不阻塞,但是第二階段拷貝數據阻塞;
  • I/O複用:可以同時等待多個IO事件;
  • 信號驅動式I/O:事件到來時通知用戶程序,用戶程序通過recv類似的系統調用讀取數據;
  • 異步I/O:兩個階段均不阻塞用戶進程;
    在這裏插入圖片描述

摘自:unix網絡編程-卷1

posix aio存在的問題

1.最大的問題就是隻對O_DIRECT方式的IO支持異步,用戶程序得自己實現I/O緩存;

  • O_DIRECT表示內核不會爲I/O數據創建buffer,硬盤數據直接通過DMA傳送到用戶程序指定的地址。所以用戶得自己管理內存和內存對齊。也就少了文件系統帶的page cache。

2.Even if you satisfy all the constraints for IO to be async, it’s sometimes not. There are a number of ways that the IO submission can end up blocking - if meta data is required to perform IO, the submission will block waiting for that. For storage devices, there are a fixed number of request slots available. If those slots are currently all in use, submission will block waiting for one to become available. These uncertainties mean that applications that rely on submission always being async are still forced to offload that part.

3.每次I/O至少需要兩次系統調用:submission和wait-for-completion。

  • aio的三個系統調用:io_setup、io_submit和io_getevents

io_uring源碼分析

1.增加對buffered io的支持,linux aio會在用戶程序submit之後被阻塞,io_uring則創建多個內核線程(2*cpu個數)去處理IO,從而防止了阻塞。

以讀取爲例,下面是io_read函數,具體看註釋:

static ssize_t io_read(struct io_kiocb *req, const struct io_uring_sqe *sqe,
		       bool force_nonblock)
{
	...
	ret = io_prep_rw(req, sqe, force_nonblock);
	ret = io_import_iovec(req->ctx, READ, sqe, &iovec, &iter);
	ret = rw_verify_area(READ, file, &kiocb->ki_pos, iov_iter_count(&iter));
	if (!ret) {
		ssize_t ret2;
		/* Catch -EAGAIN return for forced non-blocking submission */
		ret2 = call_read_iter(file, kiocb, &iter);
		if (!force_nonblock || ret2 != -EAGAIN)
			io_rw_done(kiocb, ret2);			// linux aio會在這裏等帶執行完畢
		else
			ret = -EAGAIN;						// io_uring則直接返回
	}
	return ret;
}

3.減少系統調用次數,io_uring中內核和用戶程序共享三塊內存,分別是:SQ ring、CQ ring 和 sqe array。採用producer和consumer模型,大大的降低了系統調用的次數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章