免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
嗯,不錯(cuò)難得有人可以把IO底層原理及4種主要IO模型

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

這里涉及一個(gè)基礎(chǔ)的知識:

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

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

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

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

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

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

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

文件句柄,也叫文件描述符。在Linux系統(tǒng)中,文件可分為:普通文件、目錄文件、鏈接文件和設(shè)備文件。文件描述符(File Descriptor)是內(nèi)核為了高效管理已被打開的文件所創(chuàng)建的索引,它是一個(gè)非負(fù)整數(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中,默認(rèn)創(chuàng)建的socket都是阻塞的

同步與異步

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

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

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

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

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

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

阻塞IO的缺點(diǎn)是:

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

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

同步非阻塞IO的特點(diǎn):

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

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

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

同步非阻塞IO的缺點(diǎn):

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

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

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

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

目前支持IO多路復(fù)用的系統(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增強(qiáng)版本。

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

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

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

IO多路復(fù)用模型的特點(diǎn)

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

IO多路復(fù)用模型的優(yōu)點(diǎn)

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

IO多路復(fù)用模型的缺點(diǎn)

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

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

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

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

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

異步IO模型的特點(diǎn)

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

異步IO異步模型的缺點(diǎn)

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

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

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Linux高性能服務(wù)器程序框架
如何提高服務(wù)器并發(fā)處理能力
阻塞、非阻塞、多路復(fù)用、同步、異步、BIO、NIO、AIO 一鍋端
Netty io 模型
長知識!詳解Linux五大網(wǎng)絡(luò)IO模型
c10k問題
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服