成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

I/O Multiplexing -- Linux I/O 多路復(fù)用

mengbo / 1579人閱讀

摘要:上圖中,進程調(diào)用了,系統(tǒng)函數(shù)在有數(shù)據(jù)報到達并已經(jīng)拷貝到應(yīng)用程序緩沖區(qū)時,或者有錯誤發(fā)生時才會返回最常見的錯誤是被信號中斷。多路復(fù)用在多路復(fù)用模型,我們會阻塞在這些系統(tǒng)函數(shù)中,而不是阻塞在真正的調(diào)用上。

文章還會涉及到同步 I/O,異步 I/O,阻塞 I/O 和非阻塞 I/O
首先我們需要理解以下概念:

Linux用戶態(tài)和內(nèi)核態(tài)

在現(xiàn)在操作系統(tǒng)中,CPU通常會在兩種不同的模式下工作:

內(nèi)核態(tài)

此模式下,程序代碼能夠完全,無限制地訪問底層硬件,能夠執(zhí)行任意的 CPU 指令和訪問任意的內(nèi)存地址。內(nèi)核模式通常留給最底層的,受信任的系統(tǒng)函數(shù)來使用。程序在內(nèi)核模式下崩潰是災(zāi)難性的,這甚至可以使整臺 PC 宕機。

用戶態(tài)

在用戶模式下,程序代碼不能夠直接訪問硬件和內(nèi)存。執(zhí)行在用戶態(tài)的代碼必須委托系統(tǒng)函數(shù)去訪問硬件和內(nèi)存。因為有這種隔離機制的保護,程序在用戶態(tài)下崩潰通常是可恢復(fù)的。PC 中大多數(shù)程序也是在用戶態(tài)下執(zhí)行。

進程切換

指操作系統(tǒng)進程調(diào)度切換,從某個進程到另外的進程。切換過程需要保存當前進程的所有狀態(tài),包括寄存器狀態(tài),關(guān)聯(lián)的內(nèi)核狀態(tài),虛擬內(nèi)存的配置等,具體會經(jīng)歷以下幾個步驟:

保存處理器上下文,包括程序計數(shù)器和其他寄存器

更新進程控制塊 (PCB)

移動進程的 PCB 到合適的隊列,例如就緒隊列,事件阻塞隊列

選擇其他進程,并更新他的 PCB

更新內(nèi)存數(shù)據(jù)結(jié)構(gòu)

恢復(fù) PCB 上下文

進程阻塞

一個阻塞的進程通常是在等待某個事件,例如信號的釋放或者消息的到達。在多任務(wù)的系統(tǒng)中,阻塞的進程會通過系統(tǒng)調(diào)用去通知調(diào)度器自己處于 wait 的狀態(tài),以便能夠被移除出時序隊列。進程如果在 wait 狀態(tài)下還霸占 CPU 繼續(xù)執(zhí)行,這被稱為 busy-waiting (空等?)。顯然這是不合理的,因為他浪費了 CPU 時鐘周期,這原本可以被其他進程使用。所以當一個進程進入了阻塞狀態(tài),不應(yīng)繼續(xù)占用 CPU 資源。

緩沖式 I/O

當我們寫數(shù)據(jù)(到文件系統(tǒng)),I/O 系統(tǒng)會累積數(shù)據(jù)到一個中間緩沖區(qū),當緩沖區(qū)積累到足夠數(shù)據(jù)時(或者調(diào)用flush())才會把數(shù)據(jù)發(fā)送到文件系統(tǒng),這樣減少了文件系統(tǒng)的訪問次數(shù)。因為對文件系統(tǒng)(磁盤)的訪問通常來說開銷很大(對比內(nèi)存間的拷貝),緩沖式 I/O 能夠有效提高性能,尤其是那種多次的小數(shù)據(jù)量寫操作。若是大數(shù)據(jù)量的寫操作,非緩沖式 I/O 會更好,因為緩沖式 I/O 并不會顯著減少(對文件系統(tǒng))系統(tǒng)調(diào)用,卻引入的額外的內(nèi)存拷貝工作,這些數(shù)據(jù)拷貝操作帶來了更高的 CPU 和內(nèi)存開銷。

文件描述符 (FD)

在 Unix 及其衍生的操作系統(tǒng)中,文件描述符 (FD) 是一個抽象的指示符 (原文:indicator, handle,多數(shù)文章翻譯成句柄),用來訪問文件或其他 I/O 資源,例如管道,socket等。FD 是 POSIX 編程接口的一部分,是個非負索引值,許多底層的程序都會使用到 FD

I/O 模型

當一個讀操作發(fā)生,會經(jīng)歷以下兩個階段:

數(shù)據(jù)準備階段 —— 例如等待網(wǎng)絡(luò)數(shù)據(jù)到達,當數(shù)據(jù)包到達時,他們會拷貝到內(nèi)核緩沖區(qū)中

數(shù)據(jù)轉(zhuǎn)移階段 —— 把數(shù)據(jù)從內(nèi)核拷貝到用戶進程

因為這兩個階段的存在,Linux 提供了以下5種 I/O 模型

Blocking I/O Model —— 阻塞式 I/O

阻塞式 I/O 是最常見的 I/O 模式,默認地,所有的 socket 都是阻塞式的

這里我們用 UDP 協(xié)議和 recvfrom 系統(tǒng)調(diào)用來舉例。上圖中,進程調(diào)用了 recvfrom,系統(tǒng)函數(shù)在有數(shù)據(jù)報到達并已經(jīng)拷貝到應(yīng)用程序緩沖區(qū)時,或者有錯誤發(fā)生時才會返回(最常見的錯誤是被信號中斷)。我們認為進程在 recvfrom 從調(diào)用到返回的整個階段都被阻塞了。當 recvfrom 成功返回,應(yīng)用程序才會去處理數(shù)據(jù)報。

Nonblocking I/O Model —— 非阻塞式 I/O

如果一個(數(shù)據(jù)準備階段) I/O 調(diào)用沒有完成,內(nèi)核會立即返回一個錯誤標記,而不是阻塞這個進程

第一次調(diào)用 recvfrom 時并沒有數(shù)據(jù)到達,于是內(nèi)核立即返回了錯誤標記 EWOULDBLOCK
第四次調(diào)用 recvfrom 時數(shù)據(jù)報已經(jīng)到達,拷貝到應(yīng)用程序緩沖區(qū)后,recvfrom 成功返回,之后程序會處理這些數(shù)據(jù)。
像這樣,程序在一個非阻塞的 FD 上循環(huán)調(diào)用 recvfrom 被稱為輪詢。這通常會浪費 CPU 時鐘周期,但這種模型也會偶爾使用到,例如一個系統(tǒng)只專注于某個功能的時候。

I/O Multiplexing Model —— I/O 多路復(fù)用

在 Linux I/O 多路復(fù)用模型,我們會阻塞在 select, poll, epoll 這些系統(tǒng)函數(shù)中,而不是阻塞在真正的 I/O 調(diào)用上。

上圖中,我們阻塞在 select() 函數(shù)上,等待 socket 數(shù)據(jù)可讀。select() 返回則表示 socket 數(shù)據(jù)可讀,之后我們才調(diào)用 recvfrom 拷貝數(shù)據(jù)到應(yīng)用程序緩沖區(qū)

缺點:這里我們使用了兩次系統(tǒng)調(diào)用 (select 和 recvfrom),而阻塞式 I/O 只使用了一次 recvfrom

優(yōu)勢:我們可以監(jiān)聽多個 FD 是否就緒

I/O 多路復(fù)用模型與阻塞式 I/O 模式非常相似。阻塞式 I/O 使用多線程(每個線程負責一個 FD)且每個線程都可以很自由地調(diào)用(阻塞式)系統(tǒng)函數(shù) recvfrom,而非使用 select 負責監(jiān)聽多個 FD。

Signal-Driven I/O Model —— 信號驅(qū)動 I/O

告訴內(nèi)核當某個 FD 就緒時,釋放 SIGIO 信號來通知應(yīng)用程序

我們首先讓 socket 使用信號驅(qū)動 I/O 模式,并使用 sigaction 系統(tǒng)函數(shù)注冊一個信號處理器 (signal handler),該系統(tǒng)函數(shù)立即返回,這是非阻塞的。

當數(shù)據(jù)可讀,SIGIO 信號釋放出來被進程接收到,我們可以進行如下操作之一

在 signal handler 中調(diào)用 recvfrom 讀取數(shù)據(jù),隨后通知主循環(huán)數(shù)據(jù)已經(jīng)準備好了

signal handler 通知主循環(huán)去讀取數(shù)據(jù)

該模型的優(yōu)勢在于,等待數(shù)據(jù)到達的階段不會阻塞,主循環(huán)可以繼續(xù)執(zhí)行其他任務(wù)并等待 signal handler 的通知(數(shù)據(jù)可讀或可處理)

Asynchronous I/O Model —— 異步 I/O

異步 I/O 模型告訴內(nèi)核執(zhí)行 I/O 操作,等到整個 I/O 操作(包括數(shù)據(jù)準備階段和數(shù)據(jù)轉(zhuǎn)移階段)完成后再通知我們。該模式跟信號驅(qū)動 I/O 非常相似,主要的區(qū)別是:信號驅(qū)動 I/O 中,內(nèi)核通知進程 I/O 操作可以開始(仍需把數(shù)據(jù)從內(nèi)核拷貝到進程),而異步 I/O 中內(nèi)核通知我們 I/O 操作已經(jīng)完成(數(shù)據(jù)已經(jīng)在進程緩沖區(qū)中)

我們調(diào)用了系統(tǒng)函數(shù) aio_read,向內(nèi)核傳遞了以下信息:

FD, 緩沖區(qū)指針,緩沖區(qū)大小

文件偏移量

I/O 執(zhí)行完畢的通知方式

aio_read 會立即返回,進程在等待 I/O 操作完成的整個階段都不會被阻塞。

I/O 模型的比較

前面4種模型的主要區(qū)別在第一個階段(數(shù)據(jù)準備階段),第二階段(數(shù)據(jù)轉(zhuǎn)移階段)是一樣的:進程都阻塞在數(shù)據(jù)轉(zhuǎn)移階段(從內(nèi)核拷貝到應(yīng)用程序緩沖區(qū))。異步 I/O 內(nèi)核負責這兩個階段,不需要應(yīng)用程序干預(yù)。

同步 I/O 和異步 I/O

POSIX 定義如下

同步 I/O 會導(dǎo)致請求 I/O 操作的進程阻塞,直到 I/O 操作完成

異步 I/O 不會導(dǎo)致請求 I/O 操作的進程阻塞

根據(jù)這些定義,前面4種 I/O 模型 (blocking, nonblocking, I/O multiplexing, and signal-driven I/O) 都是同步 I/O,因為實際的 I/O 操作都會阻塞進程(舉例:信號驅(qū)動 I/O 在等待數(shù)據(jù)時非阻塞,但在數(shù)據(jù)轉(zhuǎn)移時阻塞了,是同步 I/O),只有異步 I/O 模型符合定義。

select, poll, epoll

施工中

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72735.html

相關(guān)文章

  • Java NIO淺析

    摘要:阻塞請求結(jié)果返回之前,當前線程被掛起。也就是說在異步中,不會對用戶線程產(chǎn)生任何阻塞。當前線程在拿到此次請求結(jié)果的過程中,可以做其它事情。事實上,可以只用一個線程處理所有的通道。 準備知識 同步、異步、阻塞、非阻塞 同步和異步說的是服務(wù)端消息的通知機制,阻塞和非阻塞說的是客戶端線程的狀態(tài)。已客戶端一次網(wǎng)絡(luò)請求為例做簡單說明: 同步同步是指一次請求沒有得到結(jié)果之前就不返回。 異步請求不會...

    yeooo 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<