學(xué)AI,好工作 就找北大青鳥(niǎo)
關(guān)注小青 聽(tīng)課做題,輕松學(xué)習(xí)
周一至周日
4000-9696-28

大話IO

來(lái)源:北大青鳥(niǎo)總部 2023年03月16日 14:08

摘要: 在Linux的世界里,一切都是文件,都是一串二進(jìn)制流,不管是socket、FIFO、管道、終端,全都是文件,全都是流。信息交換的過(guò)程就是對(duì)流進(jìn)行數(shù)據(jù)的收發(fā)操作,也就是IO操作(Input/Output)。

“曾經(jīng)有一份真誠(chéng)的愛(ài)情放在我面前,但我沒(méi)有珍惜,等我失去的時(shí)候我才后悔莫及,人世間最痛苦的事莫過(guò)于此。”這是電影《大話西游》中的經(jīng)典臺(tái)詞,大圣與紫霞仙子最終還是沒(méi)有有情人成眷屬。然而我們今天介紹的主角-I/O與用戶,二者卻是經(jīng)歷了各種考驗(yàn),最后終成眷屬了~



那么什么是IO呢?

說(shuō)到IO就得說(shuō)到操作系統(tǒng)Linux,在Linux的世界里,一切都是文件,都是一串二進(jìn)制流,不管是socket、FIFO、管道、終端,全都是文件,全都是流。信息交換的過(guò)程就是對(duì)流進(jìn)行數(shù)據(jù)的收發(fā)操作,也就是IO操作(Input/Output)。而計(jì)算機(jī)世界里有這么多的流,通過(guò)文件描述符就可以知道操作哪個(gè)流了,通常是創(chuàng)建一個(gè)socket套接字就會(huì)產(chǎn)生一個(gè)文件描述符,所以對(duì)文件描述符的操作也就是對(duì)socket的操作,往里寫(xiě)入數(shù)據(jù)調(diào)用write,讀數(shù)據(jù)調(diào)用read。

在介紹I/O模型之前,我們要給大家先普及兩個(gè)概念:內(nèi)核空間用戶空間。簡(jiǎn)單來(lái)說(shuō),就是操作系統(tǒng)在設(shè)計(jì)時(shí)為了讓各個(gè)模塊各干各的事,劃分了不同的地盤(pán)?,F(xiàn)代操作系統(tǒng)采用虛擬存儲(chǔ)器,有32位和64位操作系統(tǒng),因此尋址地址(虛擬存儲(chǔ)空間)包含4G(2的32次方)、17179869184G(2的64次方)。操作系統(tǒng)的核心是內(nèi)核,對(duì)上可以訪問(wèn)受保護(hù)的內(nèi)存空間,對(duì)下可以訪問(wèn)底層硬件設(shè)備。為了內(nèi)核安全,保障用戶進(jìn)程不能直接操作內(nèi)核,因此操作系統(tǒng)把虛擬空間劃分為用戶空間和內(nèi)核空間。用戶空間執(zhí)行用戶自己的代碼時(shí),處于用戶態(tài);通過(guò)系統(tǒng)調(diào)用進(jìn)入內(nèi)核執(zhí)行時(shí),處于內(nèi)核態(tài)。



講完了用戶空間、內(nèi)核空間、用戶態(tài)、內(nèi)核態(tài),進(jìn)入今天的主題I/O。故事的開(kāi)始是用戶在前端發(fā)起的請(qǐng)求,當(dāng)用戶在前端發(fā)起一個(gè)請(qǐng)求時(shí),我們知道的路徑是該請(qǐng)求通過(guò)網(wǎng)絡(luò)傳遞給到后端,后端經(jīng)過(guò)業(yè)務(wù)程序調(diào)用、數(shù)據(jù)庫(kù)調(diào)用等將結(jié)果計(jì)算出來(lái),再傳遞給到前端展示結(jié)果給用戶。事實(shí)上,這背后還有更復(fù)雜的技術(shù)原理。從整個(gè)軟件系統(tǒng)來(lái)看,除了業(yè)務(wù)程序之外、還包含操作系統(tǒng)、硬件資源,因此整個(gè)用戶請(qǐng)求的處理必定是軟硬件都在參與。整個(gè)協(xié)同的過(guò)程就像人餓了要吃飯一樣,身體接收到餓了的訊息,經(jīng)由大腦處理想吃肉,再通過(guò)眼睛看到食材、雙腿獲取食材、雙手烹飪,經(jīng)過(guò)嘴巴消化之后,反饋給大腦飽了的訊息。



整個(gè)web請(qǐng)求執(zhí)行的過(guò)程如下:

  1. 用戶在客戶端發(fā)起請(qǐng)求到服務(wù)器網(wǎng)卡;

  2. 服務(wù)器網(wǎng)卡接收到請(qǐng)求后轉(zhuǎn)給內(nèi)核處理;

  3. 內(nèi)核根據(jù)請(qǐng)求對(duì)應(yīng)的套接字,將請(qǐng)求交給工作在用戶空間的web服務(wù)器進(jìn)程;

  4. web服務(wù)器進(jìn)程根據(jù)用戶請(qǐng)求,向內(nèi)核進(jìn)行系統(tǒng)調(diào)用,申請(qǐng)相應(yīng)資源;

  5. 當(dāng)web服務(wù)器進(jìn)程請(qǐng)求的是存放在本地磁盤(pán)上的資源,內(nèi)核會(huì)通過(guò)驅(qū)動(dòng)程序連接磁盤(pán);

  6. 內(nèi)核調(diào)用磁盤(pán),獲取相應(yīng)的資源;

  7. 內(nèi)核將資源存放在自己的緩存區(qū)并通知web服務(wù)器進(jìn)程;

  8. web服務(wù)器進(jìn)程通過(guò)系統(tǒng)調(diào)用取得資源,并把它復(fù)制到進(jìn)程自己的緩沖區(qū)中;

  9. web服務(wù)器進(jìn)程形成響應(yīng),通過(guò)系統(tǒng)調(diào)用再次發(fā)給內(nèi)核響應(yīng)請(qǐng)求;

  10. 內(nèi)核將響應(yīng)發(fā)給網(wǎng)卡;

  11. 網(wǎng)卡把響應(yīng)結(jié)果傳遞給到用戶。



在整個(gè)請(qǐng)求的執(zhí)行過(guò)程中,有兩次IO操作,第一次是客戶端請(qǐng)求的網(wǎng)絡(luò)I/O,第二次是web服務(wù)器請(qǐng)求磁盤(pán)I/O。因此當(dāng)應(yīng)用程序處理用戶請(qǐng)求緩慢時(shí),運(yùn)維和研發(fā)也會(huì)關(guān)注網(wǎng)絡(luò)IO和磁盤(pán)IO的情況;監(jiān)控系統(tǒng)也會(huì)包含網(wǎng)絡(luò)讀寫(xiě)速度、網(wǎng)絡(luò)發(fā)送接收包數(shù)量、磁盤(pán)讀寫(xiě)速度等指標(biāo)的監(jiān)控。

講完了為什么系統(tǒng)需要I/O,我們?cè)賮?lái)看看I/O有哪些模型?根據(jù)執(zhí)行過(guò)程和通信過(guò)程的不同,IO模型分為阻塞型、非阻塞型、IO復(fù)用型、信號(hào)驅(qū)動(dòng)型IO、異步IO。簡(jiǎn)單來(lái)說(shuō),就是這五個(gè)模型的不同在于等待數(shù)據(jù)準(zhǔn)備階段、將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程中這兩個(gè)階段不相同。


阻塞IO,即在IO操作執(zhí)行時(shí),所有其它相關(guān)的操作都不能進(jìn)行,直到IO操作執(zhí)行完成。當(dāng)在內(nèi)核執(zhí)行IO操作時(shí),應(yīng)用程序調(diào)用IO的recvform函數(shù),將應(yīng)用程序調(diào)起,不給它分配CPU時(shí)間片,進(jìn)入阻塞狀態(tài)后直到IO操作結(jié)束才返回結(jié)果;如果系統(tǒng)內(nèi)核數(shù)據(jù)沒(méi)有準(zhǔn)備好,那么就一直處理等待狀態(tài)。整個(gè)過(guò)程就像你在餐館點(diǎn)菜一樣,確認(rèn)好菜單后服務(wù)員會(huì)傳遞給到后廚,在整個(gè)期間內(nèi)你只能待在餐桌,哪里都不能去,處于阻塞等待狀態(tài),直到菜做好了,上菜后才可以走動(dòng)。



非阻塞IO,即在IO操作執(zhí)行時(shí),其它的相關(guān)操作也可以進(jìn)行。用戶線程向內(nèi)核發(fā)起IO請(qǐng)求時(shí),因?yàn)閮?nèi)核執(zhí)行也需要時(shí)間,所以先返回給用戶一個(gè)狀態(tài)值“EWOULDBLOCK”,在操作執(zhí)行過(guò)程期間,用戶線程不斷的輪詢IO請(qǐng)求,直到讀取到數(shù)據(jù)。整個(gè)過(guò)程就像你在餐館點(diǎn)菜一樣,點(diǎn)好菜后服務(wù)員會(huì)給你個(gè)訂單和號(hào)碼牌,你可以到處走動(dòng),也可以去問(wèn)廚師菜好了沒(méi)?直到上菜完成.



IO復(fù)用型,即阻塞多個(gè)I/O操作。在阻塞IO模型中,當(dāng)有IO操作進(jìn)行時(shí),系統(tǒng)進(jìn)程會(huì)被調(diào)起,這樣帶來(lái)的是效率低,因?yàn)橐粋€(gè)線程只能處理一個(gè)套接字的I/O事件。改進(jìn)方法就是調(diào)用select和poll函數(shù),當(dāng)監(jiān)聽(tīng)到有讀或?qū)懖僮鞯腎/O函數(shù)時(shí),select函數(shù)就會(huì)被調(diào)用,阻塞多個(gè)I/O操作,直到內(nèi)核監(jiān)聽(tīng)到有數(shù)據(jù)返回時(shí),select就反饋數(shù)據(jù)準(zhǔn)備好了,系統(tǒng)再調(diào)用recvfrom處理數(shù)據(jù)。整個(gè)過(guò)程就好像在餐館點(diǎn)菜就餐一樣,餐館的客人非常多,但是廚師比較少,廚師一次只能回答一個(gè)客人的問(wèn)題(如菜好了沒(méi)?),當(dāng)有了服務(wù)員的存在后,我們只需要向服務(wù)員點(diǎn)菜、下單、取菜、付費(fèi)就可以了,服務(wù)員就像我們的select函數(shù),監(jiān)聽(tīng)多個(gè)客人的下單、上菜、買單事件,直到整個(gè)任務(wù)完成。



信號(hào)驅(qū)動(dòng)型IO,即通過(guò)監(jiān)聽(tīng)信號(hào)來(lái)處理IO操作,省去了select函數(shù)的阻塞與輪詢。整個(gè)實(shí)現(xiàn)方法是在Socket套接字上安裝一個(gè)信號(hào)處理函數(shù),進(jìn)行信號(hào)驅(qū)動(dòng)I/O,用戶進(jìn)程繼續(xù)運(yùn)行并不阻塞。當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),進(jìn)程就會(huì)收到一個(gè)sigio信號(hào),此時(shí)便可調(diào)用recvfrom讀取數(shù)據(jù)。整個(gè)過(guò)程就像在餐館就餐一樣,在餐桌上有智能計(jì)菜儀,隨時(shí)感知做菜的進(jìn)度,當(dāng)有菜做好時(shí),智能計(jì)菜儀便感知到了,通知服務(wù)員或客人取菜。



異步IO模型,即同時(shí)并行多件事情。用戶進(jìn)程發(fā)起IO操作后,就去做其它的事情了,內(nèi)核接受到用戶進(jìn)程的消息時(shí),會(huì)立刻返回結(jié)果并同時(shí)等到數(shù)據(jù)準(zhǔn)備完成,再將數(shù)據(jù)拷貝到用戶內(nèi)存,當(dāng)所有的操作都完成時(shí),內(nèi)核給用戶進(jìn)程發(fā)送信號(hào)告訴它事情已搞定。整個(gè)過(guò)程就像在餐館就餐一樣,客人下單后,廚師直接接單,當(dāng)有菜做好時(shí),廚師告訴用戶,菜做好了。



在上述我們介紹了五種IO模型,五個(gè)IO模型對(duì)比如下圖所示:



經(jīng)過(guò)本文的講解,大家對(duì)計(jì)算機(jī)世界的IO掌握了嗎?我們的數(shù)據(jù)經(jīng)過(guò)了九九八十一道關(guān)卡,才最終在電腦、iPad、手機(jī)等各個(gè)終端展現(xiàn)給到用戶,每一條數(shù)據(jù)都不容易,且行且珍惜噢~



標(biāo)簽: io
熱門班型時(shí)間
人工智能就業(yè)班 即將爆滿
AI應(yīng)用線上班 即將爆滿
UI設(shè)計(jì)全能班 即將爆滿
數(shù)據(jù)分析綜合班 即將爆滿
軟件開(kāi)發(fā)全能班 爆滿開(kāi)班
網(wǎng)絡(luò)安全運(yùn)營(yíng)班 爆滿開(kāi)班
報(bào)名優(yōu)惠
免費(fèi)試聽(tīng)
課程資料
官方微信
返回頂部
培訓(xùn)課程 熱門話題 站內(nèi)鏈接