程序員應(yīng)該這樣理解IO

程序員應(yīng)該這樣理解IO

引言

很多程序員會談及IO,仿佛是種時尚或者給自己貼金的方式,因為提上它一般會涉及應(yīng)用程序的性能相關(guān)話題,離高深的底層知識更接近了。但多數(shù)人的理解其實是模糊的,他們的腦海里會浮動著抽象的場景:IO就是輸入輸出啊,電腦在磁盤上讀寫就是IO,僅此而已,或者,更高明一點,他們隱隱約約的意識到IO是個耗性能的家伙。

原諒這些膚淺的程序員吧,他們在無數(shù)個夜晚挑燈夜戰(zhàn),加班加點,做項目趕進(jìn)度,又基本沒有個人生活,還隨時可能猝死,哪里還有什么時間回爐深造,更何況作者也曾經(jīng)是他們中的一員。

什么是IO

IO是輸入input輸出output的首字母縮寫形式,直觀意思是計算機(jī)輸入輸出,它描述的是計算機(jī)的數(shù)據(jù)流動的過程,因此IO第一大特征是有數(shù)據(jù)的流動;另外,對于一次IO,它究竟是輸入還是輸出,是針對不同的主體而言的,不同的主體有不同的描述。例如,甲乙兩人交談,甲將大腦中的想法通過聲帶震動,繼而通過聲波傳入乙的耳朵,乙通過耳膜的震動再由神經(jīng)將信號解析到大腦,這個數(shù)據(jù)流動的過程對甲而言是輸出,對乙而言是輸入。

因此,理解IO一定要弄清楚所要研究的本體。

下面,我們從三個層面來理解IO。

首先,從直觀層面去理解IO。

此時,IO是計算機(jī)和外設(shè)之間的數(shù)據(jù)流動過程,本體是一個有使用意義的可運行的電腦,它是計算機(jī)運行的完全必要部分。姑且認(rèn)為這個完全必要部分是臺式電腦的主機(jī),里面有CPU、內(nèi)存、主板、電源等設(shè)備,因為有了這些,一臺有使用意義的電腦即可運行。有了主機(jī),并不能方便的為人所服務(wù),因此得有外設(shè)。外設(shè)是電腦的外圍設(shè)備,如顯示器、鍵盤、鼠標(biāo)等,它們是完成人機(jī)交互的輔助工具。外設(shè)包含兩種重要設(shè)備(但不限于此):輸入設(shè)備和輸出設(shè)備。像鼠標(biāo)鍵盤屬于輸入設(shè)備,將人的指令轉(zhuǎn)成“鼠鍵行為”這種數(shù)據(jù)傳給主機(jī);顯示器是輸出設(shè)備,主機(jī)通過運算,把“返回信息”這種數(shù)據(jù)傳給顯示器。

其次,從計算機(jī)架構(gòu)的角度去理解IO。

從計算機(jī)架構(gòu)上來講,任何涉及到計算機(jī)核心(CPU和內(nèi)存)與其他設(shè)備間的數(shù)據(jù)轉(zhuǎn)移的過程就是IO。本體就是計算機(jī)核心(CPU和內(nèi)存)。例如從硬盤上讀取數(shù)據(jù)到內(nèi)存,是一次輸入,將內(nèi)存中的數(shù)據(jù)寫入到硬盤就產(chǎn)生了輸出。在計算機(jī)的世界里,這就是IO的本質(zhì)。

最后,從編程的角度去理解IO。

此時,IO的主體是其應(yīng)用程序的運行態(tài),即進(jìn)程,特別強調(diào)的是我們的應(yīng)用程序其實并不存在實質(zhì)的IO過程,真正的IO過程是操作系統(tǒng)的事情,這里把應(yīng)用程序的IO操作分為兩種動作:IO調(diào)用和IO執(zhí)行。IO調(diào)用是由進(jìn)程發(fā)起,IO執(zhí)行是操作系統(tǒng)的工作。因此,更準(zhǔn)確些來說,此時所說的IO是應(yīng)用程序?qū)Σ僮飨到y(tǒng)IO功能的一次觸發(fā),即IO調(diào)用。

IO調(diào)用的目的是將進(jìn)程的內(nèi)部數(shù)據(jù)遷移到外部即輸出,或?qū)⑼獠繑?shù)據(jù)遷移到進(jìn)程內(nèi)部即輸入。這里,外部數(shù)據(jù)指非進(jìn)程空間數(shù)據(jù),在編程時,通常討論的場景是來自外部存儲設(shè)備的數(shù)據(jù),如硬盤、CD-ROM、以及需要socket通信傳輸?shù)木W(wǎng)絡(luò)數(shù)據(jù)。

以一個進(jìn)程的輸入類型的IO調(diào)用為例,它將完成或引起如下工作內(nèi)容:

  1. 進(jìn)程向操作系統(tǒng)請求外部數(shù)據(jù)
  2. 操作系統(tǒng)將外部數(shù)據(jù)加載到內(nèi)核緩沖區(qū)
  3. 操作系統(tǒng)將數(shù)據(jù)從內(nèi)核緩沖區(qū)拷貝到進(jìn)程緩沖區(qū)
  4. 進(jìn)程讀取數(shù)據(jù)繼續(xù)后面的工作

從上面的描述來看,我們更容易理解一個IO操作,應(yīng)用程序和操作系統(tǒng)都干了些什么,也幫助我們更容器理解阻塞和非阻塞,異步和同步的相關(guān)IO編程概念。

阻塞和非阻塞IO

阻塞和非阻塞強調(diào)的是進(jìn)程對于操作系統(tǒng)IO是否處于就緒狀態(tài)的處理方式。

上面已經(jīng)說過,應(yīng)用程序的IO實際是分為兩個步驟,IO調(diào)用和IO執(zhí)行。IO調(diào)用是由進(jìn)程發(fā)起,IO執(zhí)行是操作系統(tǒng)的工作。操作系統(tǒng)的IO情況決定了進(jìn)程IO調(diào)用是否能夠得到立即響應(yīng)。如進(jìn)程發(fā)起了讀取數(shù)據(jù)的IO調(diào)用,操作系統(tǒng)需要將外部數(shù)據(jù)拷貝到進(jìn)程緩沖區(qū),在有數(shù)據(jù)拷貝到進(jìn)程緩沖區(qū)前,進(jìn)程緩沖區(qū)處于不可讀狀態(tài),我們稱之為操作系統(tǒng)IO未就緒。

進(jìn)程的IO調(diào)用是否能得到立即執(zhí)行是需要操作系統(tǒng)IO處于就緒狀態(tài)的,對于讀取數(shù)據(jù)的操作,如果操作系統(tǒng)IO處于未就緒狀態(tài),當(dāng)前進(jìn)程或線程如果一直等待直到其就緒,該種IO方式為阻塞IO。如果進(jìn)程或線程并不一直等待其就緒,而是可以做其他事情,這種方式為非阻塞IO。所以對于非阻塞IO,我們編程時需要經(jīng)常去輪詢就緒狀態(tài)。

異步和同步IO

我們經(jīng)常會談及同步IO和異步IO。同步和異步描述的是針對當(dāng)前執(zhí)行線程、或進(jìn)程而言,發(fā)起IO調(diào)用后,當(dāng)前線程或進(jìn)程是否掛起等待操作系統(tǒng)的IO執(zhí)行完成。

我們說一個IO執(zhí)行是同步執(zhí)行的,意思是程序發(fā)起IO調(diào)用,當(dāng)前線程或進(jìn)程需要等待操作系統(tǒng)完成IO工作并告知進(jìn)程已經(jīng)完成,線程或進(jìn)程才能繼續(xù)往下執(zhí)行其他既定指令。

如果說一個IO執(zhí)行是異步的,意思是該動作是由當(dāng)前線程或進(jìn)程請求發(fā)起,且當(dāng)前線程或進(jìn)程不必等待操作系統(tǒng)IO的執(zhí)行完畢,可直接繼續(xù)往下執(zhí)行其他既定指令。操作系統(tǒng)完成IO后,當(dāng)前線程或進(jìn)程會得到操作系統(tǒng)的通知。

以一個讀取數(shù)據(jù)的IO操作而言,在操作系統(tǒng)將外部數(shù)據(jù)寫入進(jìn)程緩沖區(qū)這個期間,進(jìn)程或線程掛起等待操作系統(tǒng)IO執(zhí)行完成的話,這種IO執(zhí)行策略就為同步,如果進(jìn)程或線程并不掛起而是繼續(xù)工作,這種IO執(zhí)行策略便為異步。

總結(jié)

綜上,從編程的角度講述了程序員應(yīng)該如何去理解IO編程的一些概念。其關(guān)鍵點是要將應(yīng)用程序的IO操作分為兩個步驟來理解:IO調(diào)用和IO執(zhí)行。IO調(diào)用才是應(yīng)用程序干的事情,而IO執(zhí)行是操作系統(tǒng)的工作。在IO調(diào)用時,對待操作系統(tǒng)IO就緒狀態(tài)的不同方式,決定了其是阻塞或非阻塞模式;在IO執(zhí)行時,線程或進(jìn)程是否掛起等待IO執(zhí)行決定了其是否為同步或異步IO。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容