日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

嗯,不錯難得有人可以把IO底層原理及4種主要IO模型

 timtxu 2020-09-22

大家知道,用戶程序進行IO讀寫,依賴于操作系統(tǒng)底層的IO讀寫,基本上會用到底層的read&write兩大系統(tǒng)調(diào)用。

這里涉及一個基礎的知識:

read系統(tǒng)調(diào)用,并不是直接從物理設備把數(shù)據(jù)讀取到內(nèi)存中,write系統(tǒng)調(diào)用,也不是把數(shù)據(jù)直接寫入到物理設備

上層應用無論是調(diào)用操作系統(tǒng)的read,還是調(diào)用操作系統(tǒng)的write,都會涉及緩沖區(qū)。具體來說,調(diào)用操作系統(tǒng)的read,是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到進程緩沖區(qū);而write系統(tǒng)調(diào)用,是把數(shù)據(jù)從進程緩沖區(qū)復制到內(nèi)核緩沖區(qū)。

上圖顯示了塊數(shù)據(jù)如何從外部源(例如硬盤)移動到正在運行的進程(例如RAM)內(nèi)部的存儲區(qū)的簡化“邏輯”圖。

首先,該進程通過進行read系統(tǒng)調(diào)用來填充其緩沖區(qū)。
read讀取調(diào)用會導致內(nèi)核向磁盤控制器硬件發(fā)出命令以從磁盤獲取數(shù)據(jù)。
磁盤控制器通過DMA將數(shù)據(jù)直接寫入內(nèi)核內(nèi)存緩沖區(qū)。
磁盤控制器完成緩沖區(qū)的填充后,內(nèi)核將數(shù)據(jù)從內(nèi)核空間中的臨時緩沖區(qū)復制到進程指定的緩沖區(qū)中。

緩沖區(qū)的目的,是為了減少頻繁地與設備之間的物理交換。大家都知道,外部設備的直接讀寫,涉及操作系統(tǒng)的中斷。發(fā)生系統(tǒng)中斷時,需要保存之前的進程數(shù)據(jù)和狀態(tài)等信息,而結(jié)束中斷之后,還需要恢復之前的進程數(shù)據(jù)和狀態(tài)等信息。為了減少這種底層系統(tǒng)的時間損耗、性能損耗,于是出現(xiàn)了內(nèi)存緩沖區(qū)。

有了內(nèi)存緩沖區(qū),上層應用使用read系統(tǒng)調(diào)用時,僅僅把數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到上層應用的緩沖區(qū)(進程緩沖區(qū));上層應用使用write系統(tǒng)調(diào)用時,僅僅把數(shù)據(jù)從進程緩沖區(qū)復制到內(nèi)核緩沖區(qū)中。底層操作會對內(nèi)核緩沖區(qū)進行監(jiān)控,等待緩沖區(qū)達到一定數(shù)量的時候,再進行IO設備的中斷處理,集中執(zhí)行物理設備的實際IO操作,這種機制提升了系統(tǒng)的性能。至于什么時候中斷(讀中斷、寫中斷),由操作系統(tǒng)的內(nèi)核來決定,用戶程序則不需要關心

從數(shù)量上來說,在Linux系統(tǒng)中,操作系統(tǒng)內(nèi)核只有一個內(nèi)核緩沖區(qū)。而每個用戶程序(進程),有自己獨立的緩沖區(qū),叫作進程緩沖區(qū)。所以,用戶程序的IO讀寫程序,在大多數(shù)情況下,并沒有進行實際的IO操作,而是在進程緩沖區(qū)和內(nèi)核緩沖區(qū)之間直接進行數(shù)據(jù)的交換

文件句柄,也叫文件描述符。在Linux系統(tǒng)中,文件可分為:普通文件、目錄文件、鏈接文件和設備文件。文件描述符(File Descriptor)是內(nèi)核為了高效管理已被打開的文件所創(chuàng)建的索引,它是一個非負整數(shù)(通常是小整數(shù)),用于指代被打開的文件。所有的IO系統(tǒng)調(diào)用,包括socket的讀寫調(diào)用,都是通過文件描述符完成的。

4種主要的IO模型

介紹4種IO模型之前要先介紹兩組概念

阻塞與非阻塞

阻塞IO,指的是需要內(nèi)核IO操作徹底完成后,才返回到用戶空間執(zhí)行用戶的操作。阻塞指的是用戶空間程序的執(zhí)行狀態(tài)。傳統(tǒng)的IO模型都是同步阻塞IO。在Java中,默認創(chuàng)建的socket都是阻塞的

同步與異步

同步IO,是一種用戶空間與內(nèi)核空間的IO發(fā)起方式。同步IO是指用戶空間的線程是主動發(fā)起IO請求的一方,內(nèi)核空間是被動接受方。異步IO則反過來,是指系統(tǒng)內(nèi)核是主動發(fā)起IO請求的一方,用戶空間的線程是被動接受方

在Java應用程序進程中,默認情況下,所有的socket連接的IO操作都是同步阻塞IO(Blocking IO)。

在阻塞式IO模型中,Java應用程序從IO系統(tǒng)調(diào)用開始,直到系統(tǒng)調(diào)用返回,在這段時間內(nèi),Java進程是阻塞的。返回成功后,應用進程開始處理用戶空間的緩存區(qū)數(shù)據(jù)。

從Java啟動IO讀的read系統(tǒng)調(diào)用開始,用戶線程就進入阻塞狀態(tài)。
當系統(tǒng)內(nèi)核收到read系統(tǒng)調(diào)用,就開始準備數(shù)據(jù)。一開始,數(shù)據(jù)可能還沒有到達內(nèi)核緩沖區(qū)(例如,還沒有收到一個完整的socket數(shù)據(jù)包),這個時候內(nèi)核就要等待。
內(nèi)核一直等到完整的數(shù)據(jù)到達,就會將數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到用戶緩沖區(qū)(用戶空間的內(nèi)存),然后內(nèi)核返回結(jié)果(例如返回復制到用戶緩沖區(qū)中的字節(jié)數(shù))。
直到內(nèi)核返回后,用戶線程才會解除阻塞的狀態(tài),重新運行起來。

阻塞IO的優(yōu)點是:

應用的程序開發(fā)非常簡單;在阻塞等待數(shù)據(jù)期間,用戶線程掛起。在阻塞期間,用戶線程基本不會占用CPU資源。

阻塞IO的缺點是:

一般情況下,會為每個連接配備一個獨立的線程;反過來說,就是一個線程維護一個連接的IO操作。在并發(fā)量小的情況下,這樣做沒有什么問題。但是,當在高并發(fā)的應用場景下,需要大量的線程來維護大量的網(wǎng)絡連接,內(nèi)存、線程切換開銷會非常巨大。因此,基本上阻塞IO模型在高并發(fā)應用場景下是不可用的。

在內(nèi)核數(shù)據(jù)沒有準備好的階段,用戶線程發(fā)起IO請求時,立即返回。所以,為了讀取到最終的數(shù)據(jù),用戶線程需要不斷地發(fā)起IO系統(tǒng)調(diào)用。
內(nèi)核數(shù)據(jù)到達后,用戶線程發(fā)起系統(tǒng)調(diào)用,用戶線程阻塞。內(nèi)核開始復制數(shù)據(jù),它會將數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到用戶緩沖區(qū)(用戶空間的內(nèi)存),然后內(nèi)核返回結(jié)果(例如返回復制到的用戶緩沖區(qū)的字節(jié)數(shù))。
用戶線程讀到數(shù)據(jù)后,才會解除阻塞狀態(tài),重新運行起來。也就是說,用戶進程需要經(jīng)過多次的嘗試,才能保證最終真正讀到數(shù)據(jù),而后繼續(xù)執(zhí)行。

同步非阻塞IO的特點:

應用程序的線程需要不斷地進行IO系統(tǒng)調(diào)用,輪詢數(shù)據(jù)是否已經(jīng)準備好,如果沒有準備好,就繼續(xù)輪詢,直到完成IO系統(tǒng)調(diào)用為止。

同步非阻塞IO的優(yōu)點:

每次發(fā)起的IO系統(tǒng)調(diào)用,在內(nèi)核等待數(shù)據(jù)過程中可以立即返回。用戶線程不會阻塞,實時性較好。

同步非阻塞IO的缺點:

不斷地輪詢內(nèi)核,這將占用大量的CPU時間,效率低下

總體來說,在高并發(fā)應用場景下,同步非阻塞IO也是不可用的。一般Web服務器不使用這種IO模型。這種IO模型一般很少直接使用,而是在其他IO模型中使用非阻塞IO這一特性。在Java的實際開發(fā)中,也不會涉及這種IO模型

如何避免同步非阻塞IO模型中輪詢等待的問題呢?這就是IO多路復用模型

在IO多路復用模型中,引入了一種新的系統(tǒng)調(diào)用,查詢IO的就緒狀態(tài)。在Linux系統(tǒng)中,對應的系統(tǒng)調(diào)用為select/epoll系統(tǒng)調(diào)用。通過該系統(tǒng)調(diào)用,一個進程可以監(jiān)視多個文件描述符,一旦某個描述符就緒(一般是內(nèi)核緩沖區(qū)可讀/可寫),內(nèi)核能夠?qū)⒕途w的狀態(tài)返回給應用程序。隨后,應用程序根據(jù)就緒的狀態(tài),進行相應的IO系統(tǒng)調(diào)用。

目前支持IO多路復用的系統(tǒng)調(diào)用,有select、epoll等等。select系統(tǒng)調(diào)用,幾乎在所有的操作系統(tǒng)上都有支持,具有良好的跨平臺特性。epoll是在Linux 2.6內(nèi)核中提出的,是select系統(tǒng)調(diào)用的Linux增強版本。

在IO多路復用模型中通過select/epoll系統(tǒng)調(diào)用,單個應用程序的線程,可以不斷地輪詢成百上千的socket連接,當某個或者某些socket網(wǎng)絡連接有IO就緒的狀態(tài),就返回對應的可以執(zhí)行的讀寫操作

舉個例子來說明IO多路復用模型的流程。發(fā)起一個多路復用IO的read讀操作的系統(tǒng)調(diào)用,流程如下:

選擇器注冊。在這種模式中,首先,將需要read操作的目標socket網(wǎng)絡連接,提前注冊到select/epoll選擇器中,Java中對應的選擇器類是Selector類。然后,才可以開啟整個IO多路復用模型的輪詢流程。
就緒狀態(tài)的輪詢。通過選擇器的查詢方法,查詢注冊過的所有socket連接的就緒狀態(tài)。通過查詢的系統(tǒng)調(diào)用,內(nèi)核會返回一個就緒的socket列表。當任何一個注冊過的socket中的數(shù)據(jù)準備好了,內(nèi)核緩沖區(qū)有數(shù)據(jù)(就緒)了,內(nèi)核就將該socket加入到就緒的列表中。 當用戶進程調(diào)用了select查詢方法,那么整個線程會被阻塞掉。
用戶線程獲得了就緒狀態(tài)的列表后,根據(jù)其中的socket連接,發(fā)起read系統(tǒng)調(diào)用,用戶線程阻塞。內(nèi)核開始復制數(shù)據(jù),將數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到用戶緩沖區(qū)。
復制完成后,內(nèi)核返回結(jié)果,用戶線程才會解除阻塞的狀態(tài),用戶線程讀取到了數(shù)據(jù),繼續(xù)執(zhí)行。

IO多路復用模型的特點

涉及兩種系統(tǒng)調(diào)用(System Call),
一種是select/epoll(就緒查詢)
一種是IO操作。
和NIO模型相似,多路復用IO也需要輪詢。負責select/epoll狀態(tài)查詢調(diào)用的線程,需要不斷地進行select/epoll輪詢,查找出達到IO操作就緒的socket連接。

IO多路復用模型的優(yōu)點

與一個線程維護一個連接的阻塞IO模式相比,使用select/epoll的最大優(yōu)勢在于,一個選擇器查詢線程可以同時處理成千上萬個連接(Connection)。系統(tǒng)不必創(chuàng)建大量的線程,也不必維護這些線程,從而大大減小了系統(tǒng)的開銷。

IO多路復用模型的缺點

本質(zhì)上,select/epoll系統(tǒng)調(diào)用是阻塞式的,屬于同步IO。都需要在讀寫事件就緒后,由系統(tǒng)調(diào)用本身負責進行讀寫,也就是說這個讀寫過程是阻塞的

如果要徹底地解除線程的阻塞,就必須使用異步IO模型

異步IO模型(Asynchronous IO,簡稱為AIO)。AIO的基本流程是:用戶線程通過系統(tǒng)調(diào)用,向內(nèi)核注冊某個IO操作。內(nèi)核在整個IO操作(包括數(shù)據(jù)準備、數(shù)據(jù)復制)完成后,通知用戶程序,用戶執(zhí)行后續(xù)的業(yè)務操作。

舉個例子。發(fā)起一個異步IO的read讀操作的系統(tǒng)調(diào)用,流程如下:

當用戶線程發(fā)起了read系統(tǒng)調(diào)用,立刻就可以開始去做其他的事,用戶線程不阻塞。
內(nèi)核就開始了IO的第一個階段:準備數(shù)據(jù)。等到數(shù)據(jù)準備好了,內(nèi)核就會將數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到用戶緩沖區(qū)(用戶空間的內(nèi)存)。
內(nèi)核會給用戶線程發(fā)送一個信號(Signal),或者回調(diào)用戶線程注冊的回調(diào)接口,告訴用戶線程read操作完成了。
用戶線程讀取用戶緩沖區(qū)的數(shù)據(jù),完成后續(xù)的業(yè)務操作。

異步IO模型的特點

在內(nèi)核等待數(shù)據(jù)和復制數(shù)據(jù)的兩個階段,用戶線程都不是阻塞的。用戶線程需要接收內(nèi)核的IO操作完成的事件,或者用戶線程需要注冊一個IO操作完成的回調(diào)函數(shù)。正因為如此,異步IO有的時候也被稱為信號驅(qū)動IO

異步IO異步模型的缺點

應用程序僅需要進行事件的注冊與接收,其余的工作都留給了操作系統(tǒng),也就是說,需要底層內(nèi)核提供支持。 理論上來說,異步IO是真正的異步輸入輸出,它的吞吐量高于IO多路復用模型的吞吐量

就目前而言,Windows系統(tǒng)下通過IOCP實現(xiàn)了真正的異步IO。而在Linux系統(tǒng)下,異步IO模型在2.6版本才引入,目前并不完善,其底層實現(xiàn)仍使用epoll,與IO多路復用相同,因此在性能上沒有明顯的優(yōu)勢。 大多數(shù)的高并發(fā)服務器端的程序,一般都是基于Linux系統(tǒng)的。因而,目前這類高并發(fā)網(wǎng)絡應用程序的開發(fā),大多采用IO多路復用模型

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多