Linux 核心101 非同步IO

2021-09-24 07:08:39 字數 3051 閱讀 7158

posix 非同步 io inte***ce(aio)定義了允許程序建立乙個或多個非同步的 io 操作的介面。程序可以在 io 操作完成之後得到作業系統的通知,手段包括:不通知、訊號、例項化thread。

注意:這只是 posix(the portable operating system inte***ce)定義的介面,並不是實現。linux 核心對非同步 io 的具體實現在後面。(this is an api, not implementation!

posix 1003.1標準定義了非同步訪問檔案的 library function:

系統呼叫

描述aio_read()

非同步讀取檔案

aio_write()

非同步寫入檔案

aio_fsync

發出對當前所有 outstanding 的非同步io操作進行 flush 的請求 (不會阻塞)

aio_error()

獲取乙個處於 outstanding 狀態非同步 io 操作的 error code

aio_return()

獲取乙個已經完成的非同步 io 操作的返回碼

aio_cancel()

取消乙個outstanding的非同步 io 操作

aio_suspend()

暫停程序,直到至少有乙個outstanding的非同步 io 操作完成

使用非同步 io 其實是很簡單的。大致來說分為三步:

程式先是使用普通的open()系統呼叫。

然後建立乙個叫做aiocb的 control block填滿,比較重要的一些字段如下:

具體的定義如下:

#include 

struct aiocb ;

/* operation codes for

'aio_lio_opcode': */

enum ;

複製**

最後把aiocb這個 control block 的位址傳給aio_read()或者aio_write()

這兩個函式都會在kernel或library將對應 io 的資料傳輸加入傳輸佇列之後立即退出。

之後程序可以用aio_error()檢查非同步 io 的進行狀態:

aio_error()返回值

描述einprogress

還在傳輸中

0成功完成

其他錯誤碼

操作失敗

可以用aio_return()獲取成功read或write了多少個 bytes,或者-1表示失敗。

在作業系統核心不支援非同步 io 的情況下,非同步 io 也能夠實現,實現思路如下:aio_read()aio_write()先轉殖當前程序,讓子程序執行同步的read()write()系統呼叫,然後父程序結束aio_read()aio_write(),從而實現非阻塞,主程序可以開始做其他事情。顯然,這種沒有得到核心支援的非同步 io 操作是比較低效的。

linux 核心從2.6版本起開始支援下面這些系統呼叫:

系統呼叫

描述io_setup()

為當前程序建立乙個非同步io上下文(asynchronous i/o contex)

io_submit()

提交乙個或多個非同步 io 操作

io_getevents()

獲取一些 outstanding 非同步 io 的執行狀態

io_cancel()

取消乙個非同步 io

io_destroy()

摧毀當前程序的非同步 io 上下文

使用者態的程序要呼叫io_submit()之前,先得呼叫io_setup()建立非同步 io 上下文。

基本上來說,乙個 aio context 就是乙個用於追蹤所有進行中的非同步io操作的資料結構,這個 struct 叫做kioctx。乙個應用可能會建立多個 aio context,乙個程序的所有kioctx用乙個鍊錶相連:ioctx_list

這個ioctx_list儲存在該程序的memory descriptor上:

**於《understanding the linux kernel, third edition》 p355

kioctx中有乙個重要的資料結構:aio ringaio ring的作用是:kernel 把 outstanding 的 非同步 io 操作完成情況寫到這裡面,由於aio ring是位於程序的位址空間的,所以程序可以直接從這個資料介面裡面讀取非同步 io 的狀態,而不用執行相對較慢的系統呼叫。

aio_submit()系統呼叫包含三個引數:

其中iocb和 posix 標準中的aiocb是一樣的,同樣包含aio_fildes, aio_buf, aio_nbytes, aio_offset, aio_lio_opcode這些字段。

linux kernel 有乙個 service routine :sys_io_submit(),執行下列操作:

檢查iocbpp列表包含的iocbdescriptors是不是合法的。

通過xtx_idioctx_list中檢索出對應的kioctx

對每乙個iocbdescriptor,執行下列操作:

Linux核心開發之非同步通知與非同步I O 一

小王,聽說過錦上添花吧.我拍拍下王的頭說。還錦上添花你,為你上次提的幾個東東,我是頭上長包.小王氣憤地瞪著我。啊,為啥這樣呢,本來還特意拒絕了mm的約會,抽出時間打算給你說點高階的東東,看來現在是不行了 我吃驚道,這樣吧,這次就給你講些和前邊有關的東西,也不失為錦上添花不是?好,我也是這麼打算的,就...

Linux核心開發之非同步通知與非同步I O 二

曾經有乙份真摯的愛情擺在面前,我卻不懂珍惜 曾經有乙個承諾,我卻倍感珍惜,今天一定要好好講講.講講啥,講講上節說的那個非同步通知的例子唄,大家喜歡看 咋們就先上 struct globalfifo dev 檔案釋放函式 int globalfifo release struct inode inod...

Linux核心開發之非同步通知與非同步I O 五

小王呢,今天開始講aio與裝置驅動,這也是裝置驅動通知與非同步io的最後一節了,下次咱們就要開始講更高階的東西,比如中斷啦,時鐘等 在linux核心中,每個io請求都對應乙個kiocb結構體,其ki filp成員指向對應的file指標,通過is sync kiocb可以判斷某kiocb時候為同步io...