国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

I/O Multiplexing -- Linux I/O 多路復用

mengbo / 1574人閱讀

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

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

Linux用戶態和內核態

在現在操作系統中,CPU通常會在兩種不同的模式下工作:

內核態

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

用戶態

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

進程切換

指操作系統進程調度切換,從某個進程到另外的進程。切換過程需要保存當前進程的所有狀態,包括寄存器狀態,關聯的內核狀態,虛擬內存的配置等,具體會經歷以下幾個步驟:

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

更新進程控制塊 (PCB)

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

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

更新內存數據結構

恢復 PCB 上下文

進程阻塞

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

緩沖式 I/O

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

文件描述符 (FD)

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

I/O 模型

當一個讀操作發生,會經歷以下兩個階段:

數據準備階段 —— 例如等待網絡數據到達,當數據包到達時,他們會拷貝到內核緩沖區中

數據轉移階段 —— 把數據從內核拷貝到用戶進程

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

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

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

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

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

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

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

I/O Multiplexing Model —— I/O 多路復用

在 Linux I/O 多路復用模型,我們會阻塞在 select, poll, epoll 這些系統函數中,而不是阻塞在真正的 I/O 調用上。

上圖中,我們阻塞在 select() 函數上,等待 socket 數據可讀。select() 返回則表示 socket 數據可讀,之后我們才調用 recvfrom 拷貝數據到應用程序緩沖區

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

優勢:我們可以監聽多個 FD 是否就緒

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

Signal-Driven I/O Model —— 信號驅動 I/O

告訴內核當某個 FD 就緒時,釋放 SIGIO 信號來通知應用程序

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

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

在 signal handler 中調用 recvfrom 讀取數據,隨后通知主循環數據已經準備好了

signal handler 通知主循環去讀取數據

該模型的優勢在于,等待數據到達的階段不會阻塞,主循環可以繼續執行其他任務并等待 signal handler 的通知(數據可讀或可處理)

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

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

我們調用了系統函數 aio_read,向內核傳遞了以下信息:

FD, 緩沖區指針,緩沖區大小

文件偏移量

I/O 執行完畢的通知方式

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

I/O 模型的比較

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

同步 I/O 和異步 I/O

POSIX 定義如下

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

異步 I/O 不會導致請求 I/O 操作的進程阻塞

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

select, poll, epoll

施工中

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72735.html

相關文章

  • Java NIO淺析

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

    yeooo 評論0 收藏0

發表評論

0條評論

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