一、I/O與CPU時(shí)間的比較
I/O 操作比在內(nèi)存中進(jìn)行數(shù)據(jù)處理任務(wù)所需時(shí)間更長,差別要以數(shù)量級(jí)計(jì)。許多程序員一門心思撲在他們的對(duì)象如何加工數(shù)據(jù)上,對(duì)影響數(shù)據(jù)讀取和存儲(chǔ)的環(huán)境問題卻不屑一顧。
表 1-1 所示為對(duì)數(shù)據(jù)單元進(jìn)行磁盤讀寫所需時(shí)間的假設(shè)值。
- 第一列為處理一個(gè)數(shù)據(jù)單元所需平均時(shí)間
- 第二列為對(duì)該數(shù)據(jù)單元進(jìn)行磁盤讀寫所需時(shí)間
- 第三列為每秒所能處理的數(shù)據(jù)單元數(shù)
- 第四列為改變第一第二列的值所能產(chǎn)生的數(shù)據(jù)吞吐率的提升值
前三行顯示了處理階段的效率提升會(huì)如何影響吞吐率。把單位處理時(shí)間減半,僅能提高吞吐率 2.2%。而另一方面,僅僅縮短 I/O 延遲 10%,就可使吞吐率增加 9.7%;把 I/O 時(shí)間減半,吞吐率幾乎翻番。當(dāng)您了解到 I/O 花在一個(gè)數(shù)據(jù)單元上的時(shí)間是處理時(shí)間的 20 倍,這樣的結(jié)果就不足為奇了。表中所列并非真實(shí)數(shù)據(jù),目的只在說明相對(duì)時(shí)間度量,現(xiàn)實(shí)情況絕非如此簡單。正如您所看到的,影響應(yīng)用程序執(zhí)行效率的限定性因素,往往并非處理速率,而是 I/O。
二、用戶空間與內(nèi)核空間
現(xiàn)在操作系統(tǒng)都是采用虛擬存儲(chǔ)器,那么對(duì)32位操作系統(tǒng)而言,它的尋址空間(虛擬存儲(chǔ)空間)為4G(2的32次方)。操作系統(tǒng)的核心是內(nèi)核,獨(dú)立于普通的應(yīng)用程序,可以訪問受保護(hù)的內(nèi)存空間,也有訪問底層硬件設(shè)備的所有權(quán)限。為了保證用戶進(jìn)程不能直接操作內(nèi)核(kernel),保證內(nèi)核的安全,操心系統(tǒng)將虛擬空間劃分為兩部分,一部分為內(nèi)核空間,一部分為用戶空間。針對(duì)linux操作系統(tǒng)而言,將最高的1G字節(jié)(從虛擬地址0xC0000000到0xFFFFFFFF),供內(nèi)核使用,稱為內(nèi)核空間,而將較低的3G字節(jié)(從虛擬地址0x00000000到0xBFFFFFFF),供各個(gè)進(jìn)程使用,稱為用戶空間。
三、緩沖區(qū)操作
緩沖區(qū),以及緩沖區(qū)如何工作,是所有 I/O 的基礎(chǔ)。所謂“輸入/輸出”講的無非就是把數(shù)據(jù)移進(jìn)或移出緩沖區(qū)。進(jìn)程執(zhí)行 I/O 操作,歸結(jié)起來,也就是向操作系統(tǒng)發(fā)出請(qǐng)求,讓它要么把緩沖區(qū)里的數(shù)據(jù)排干(寫),要么用數(shù)據(jù)把緩沖區(qū)填滿(讀)。進(jìn)程使用這一機(jī)制處理所有數(shù)據(jù)進(jìn)出操作。操作系統(tǒng)內(nèi)部處理這一任務(wù)的機(jī)制,其復(fù)雜程度可能超乎想像,但就概念而言,卻非常直白易懂。
圖中明顯忽略了很多細(xì)節(jié),僅顯示了涉及到的基本步驟。
上圖1.1 簡單描述了數(shù)據(jù)從外部磁盤向運(yùn)行中的進(jìn)程的內(nèi)存區(qū)域移動(dòng)的過程。進(jìn)程使用 read( )系 統(tǒng)調(diào)用,要求其緩沖區(qū)被填滿。內(nèi)核隨即向磁盤控制硬件發(fā)出命令,要求其從磁盤讀取數(shù)據(jù)。磁盤控制器把數(shù)據(jù)直接寫入內(nèi)核內(nèi)存緩沖區(qū),這一步通過 DMA 完成,無需主 CPU 協(xié)助。一旦磁盤控制器把緩沖區(qū)裝滿,內(nèi)核即把數(shù)據(jù)從內(nèi)核空間的臨時(shí)緩沖區(qū)拷貝到進(jìn)程執(zhí)行 read( )調(diào)用時(shí)指定的緩沖區(qū)。
注意圖中用戶空間和內(nèi)核空間的概念。用戶空間是常規(guī)進(jìn)程所在區(qū)域。 JVM 就是常規(guī)進(jìn)程,
駐守于用戶空間。用戶空間是非特權(quán)區(qū)域:比如,在該區(qū)域執(zhí)行的代碼就不能直接訪問硬件設(shè)備。內(nèi)核空間是操作系統(tǒng)所在區(qū)域。內(nèi)核代碼有特別的權(quán)力:它能與設(shè)備控制器通訊,控制著用戶區(qū)域進(jìn)程的運(yùn)行狀態(tài),等等。最重要的是,所有 I/O 都直接(如這里所述)或間接通
過內(nèi)核空間。
當(dāng)進(jìn)程請(qǐng)求 I/O 操作的時(shí)候,它執(zhí)行一個(gè)系統(tǒng)調(diào)用(有時(shí)稱為陷阱)將控制權(quán)移交給內(nèi)核。
C/C++程序員所熟知的底層函數(shù) open( )、 read( )、 write( )和 close( )要做的無非就是建立和執(zhí)行適當(dāng)?shù)南到y(tǒng)調(diào)用。當(dāng)內(nèi)核以這種方式被調(diào)用,它隨即采取任何必要步驟,找到進(jìn)程所需數(shù)據(jù),并把數(shù)據(jù)傳送到用戶空間內(nèi)的指定緩沖區(qū)。內(nèi)核試圖對(duì)數(shù)據(jù)進(jìn)行高速緩存或預(yù)讀取,因此進(jìn)程所需數(shù)據(jù)可能已經(jīng)在內(nèi)核空間里了。如果是這樣,該數(shù)據(jù)只需簡單地拷貝出來即可。如果數(shù)據(jù)不在內(nèi)核空間,則進(jìn)程被掛起,內(nèi)核著手把數(shù)據(jù)讀進(jìn)內(nèi)存。
看了圖 1-1,您可能會(huì)覺得,把數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間似乎有些多余。為什么不直接
讓磁盤控制器把數(shù)據(jù)送到用戶空間的緩沖區(qū)呢?這樣做有幾個(gè)問題。
- 首先,硬件通常不能直接訪問用戶空間 。
- 其次,像磁盤這樣基于塊存儲(chǔ)的硬件設(shè)備操作的是固定大小的數(shù)據(jù)塊,而用戶進(jìn)程請(qǐng)求的可能是任意大小的或非對(duì)齊的數(shù)據(jù)塊。
- 在數(shù)據(jù)往來于用戶空間與存儲(chǔ)設(shè)備的過程中,內(nèi)核負(fù)責(zé)數(shù)據(jù)的分解、再組合工作,因此充當(dāng)著中間人的角色。
四、發(fā)散/匯聚
許多操作系統(tǒng)能把組裝/分解過程進(jìn)行得更加高效。根據(jù)發(fā)散/匯聚的概念,進(jìn)程只需一個(gè)系
統(tǒng)調(diào)用,就能把一連串緩沖區(qū)地址傳遞給操作系統(tǒng)。然后,內(nèi)核就可以順序填充或排干多個(gè)緩沖
區(qū),讀的時(shí)候就把數(shù)據(jù)發(fā)散到多個(gè)用戶空間緩沖區(qū),寫的時(shí)候再從多個(gè)緩沖區(qū)把數(shù)據(jù)匯聚起來,如下 圖。
圖 1-2. 三個(gè)緩沖區(qū)的發(fā)散讀操作
這樣用戶進(jìn)程就不必多次執(zhí)行系統(tǒng)調(diào)用(那樣做可能代價(jià)不菲),內(nèi)核也可以優(yōu)化數(shù)據(jù)的處理
過程,因?yàn)樗颜莆沾齻鬏敂?shù)據(jù)的全部信息。如果系統(tǒng)配有多個(gè) CPU,甚至可以同時(shí)填充或排干多個(gè)緩沖區(qū)
五、虛擬內(nèi)存
所有現(xiàn)代操作系統(tǒng)都使用虛擬內(nèi)存。虛擬內(nèi)存意為使用虛假(或虛擬)地址取代物理(硬件
RAM)內(nèi)存地址。這樣做好處頗多,總結(jié)起來可分為兩大類:
- 一個(gè)以上的虛擬地址可指向同一個(gè)物理內(nèi)存地址。
- 虛擬內(nèi)存空間可大于實(shí)際可用的硬件內(nèi)存。
前面提到,設(shè)備控制器不能通過 DMA 直接存儲(chǔ)到用戶空間,但通過利用上面提到的第一項(xiàng),則可以達(dá)到相同效果。把內(nèi)核空間地址與用戶空間的虛擬地址映射到同一個(gè)物理地址,這樣,
DMA 硬件(只能訪問物理內(nèi)存地址)就可以填充對(duì)內(nèi)核與用戶空間進(jìn)程同時(shí)可見的緩沖區(qū),如下圖。
這樣省去了內(nèi)核與用戶空間的往來拷貝,但前提條件是,內(nèi)核與用戶緩沖區(qū)必須使用相同的頁對(duì)齊,緩沖區(qū)的大小還必須是磁盤控制器塊大?。ㄍǔ?512 字節(jié)磁盤扇區(qū))的倍數(shù)。操作系統(tǒng)把內(nèi)存地址空間劃分為頁,即固定大小的字節(jié)組。內(nèi)存頁的大小總是磁盤塊大小的倍數(shù),通常為 2 次冪(這樣可簡化尋址操作)。典型的內(nèi)存頁為 1,024、 2,048 和 4,096 字節(jié)。虛擬和物理內(nèi)存頁的大小總是相同的。圖 1-4 顯示了來自多個(gè)虛擬地址的虛擬內(nèi)存頁是如何映射到物理內(nèi)的。
六、內(nèi)存頁面調(diào)度
為了支持虛擬內(nèi)存的第二個(gè)特性(尋址空間大于物理內(nèi)存),就必須進(jìn)行虛擬內(nèi)存分頁(經(jīng)常
稱為交換,雖然真正的交換是在進(jìn)程層面完成,而非頁層面)。依照該方案,虛擬內(nèi)存空間的頁面能夠繼續(xù)存在于外部磁盤存儲(chǔ),這樣就為物理內(nèi)存中的其他虛擬頁面騰出了空間。從本質(zhì)上說,物理內(nèi)存充當(dāng)了分頁區(qū)的高速緩存;而所謂分頁區(qū),即從物理內(nèi)存置換出來,轉(zhuǎn)而存儲(chǔ)于磁盤上的內(nèi)存頁面。
圖 1-5 顯示了分屬于四個(gè)進(jìn)程的虛擬頁面,其中每個(gè)進(jìn)程都有屬于自己的虛擬內(nèi)存空間。進(jìn)程A 有五個(gè)頁面,其中兩個(gè)裝入內(nèi)存,其余存儲(chǔ)于磁盤。
圖 1-5. 用于分頁區(qū)高速緩存的物理內(nèi)存
把內(nèi)存頁大小設(shè)定為磁盤塊大小的倍數(shù),這樣內(nèi)核就可直接向磁盤控制硬件發(fā)布命令,把內(nèi)存
頁寫入磁盤,在需要時(shí)再重新裝入。結(jié)果是,所有磁盤 I/O 都在頁層面完成。對(duì)于采用分頁技術(shù)的現(xiàn)代操作系統(tǒng)而言,這也是數(shù)據(jù)在磁盤與物理內(nèi)存之間往來的唯一方式。
現(xiàn)代 CPU 包含一個(gè)稱為內(nèi)存管理單元(MMU)的子系統(tǒng),邏輯上位于 CPU 與物理內(nèi)存之
間。該設(shè)備包含虛擬地址向物理內(nèi)存地址轉(zhuǎn)換時(shí)所需映射信息。當(dāng) CPU 引用某內(nèi)存地址時(shí), MMU負(fù)責(zé)確定該地址所在頁(往往通過對(duì)地址值進(jìn)行移位或屏蔽位操作實(shí)現(xiàn)),并將虛擬頁號(hào)轉(zhuǎn)換為物理頁號(hào)(這一步由硬件完成,速度極快)。如果當(dāng)前不存在與該虛擬頁形成有效映射的物理內(nèi)存頁, MMU 會(huì)向 CPU 提交一個(gè)頁錯(cuò)誤。
頁錯(cuò)誤隨即產(chǎn)生一個(gè)陷阱(類似于系統(tǒng)調(diào)用),把控制權(quán)移交給內(nèi)核,附帶導(dǎo)致錯(cuò)誤的虛擬地址信息,然后內(nèi)核采取步驟驗(yàn)證頁的有效性。內(nèi)核會(huì)安排頁面調(diào)入操作,把缺失的頁內(nèi)容讀回物理內(nèi)存。這往往導(dǎo)致別的頁被移出物理內(nèi)存,好給新來的頁讓地方。在這種情況下,如果待移出的頁已經(jīng)被碰過了(自創(chuàng)建或上次頁面調(diào)入以來,內(nèi)容已發(fā)生改變),還必須首先執(zhí)行頁面調(diào)出,把頁內(nèi)容拷貝到磁盤上的分頁區(qū)。
如果所要求的地址不是有效的虛擬內(nèi)存地址(不屬于正在執(zhí)行的進(jìn)程的任何一個(gè)內(nèi)存段),則該頁不能通過驗(yàn)證,段錯(cuò)誤隨即產(chǎn)生。于是,控制權(quán)轉(zhuǎn)交給內(nèi)核的另一部分,通常導(dǎo)致的結(jié)果就是進(jìn)程被強(qiáng)令關(guān)閉。
一旦出錯(cuò)的頁通過了驗(yàn)證, MMU 隨即更新,建立新的虛擬到物理的映射(如有必要,中斷被移出頁的映射),用戶進(jìn)程得以繼續(xù)。造成頁錯(cuò)誤的用戶進(jìn)程對(duì)此不會(huì)有絲毫察覺,一切都在不知不覺中進(jìn)行。
七、文件I/O
文件 I/O 屬文件系統(tǒng)范疇,文件系統(tǒng)與磁盤迥然不同。磁盤把數(shù)據(jù)存在扇區(qū)上,通常一個(gè)扇區(qū)
512 字節(jié)。磁盤屬硬件設(shè)備,對(duì)何謂文件一無所知,它只是提供了一系列數(shù)據(jù)存取窗口。在這點(diǎn)
上,磁盤扇區(qū)與內(nèi)存頁頗有相似之處:都是統(tǒng)一大小,都可作為大的數(shù)組被訪問。
文件系統(tǒng)是更高層次的抽象,是安排、解釋磁盤(或其他隨機(jī)存取塊設(shè)備)數(shù)據(jù)的一種獨(dú)特方
式。您所寫代碼幾乎無一例外地要與文件系統(tǒng)打交道,而不是直接與磁盤打交道。是文件系統(tǒng)定義了文件名、路徑、文件、文件屬性等抽象概念。
前面講到,所有 I/O 都是通過請(qǐng)求頁面調(diào)度完成的。您應(yīng)該還記得,頁面調(diào)度是非常底層的
操作,僅發(fā)生于磁盤扇區(qū)與內(nèi)存頁之間的直接傳輸。而文件 I/O 則可以任意大小、任意定位。那么,底層的頁面調(diào)度是如何轉(zhuǎn)換為文件 I/O 的?
文件系統(tǒng)把一連串大小一致的數(shù)據(jù)塊組織到一起。有些塊存儲(chǔ)元信息,如空閑塊、目錄、索引
等的映射,有些包含文件數(shù)據(jù)。單個(gè)文件的元信息描述了哪些塊包含文件數(shù)據(jù)、數(shù)據(jù)在哪里結(jié)束、最后一次更新是什么時(shí)候,等等。
當(dāng)用戶進(jìn)程請(qǐng)求讀取文件數(shù)據(jù)時(shí),文件系統(tǒng)需要確定數(shù)據(jù)具體在磁盤什么位置,然后著手把相關(guān)磁盤扇區(qū)讀進(jìn)內(nèi)存。老式的操作系統(tǒng)往往直接向磁盤驅(qū)動(dòng)器發(fā)布命令,要求其讀取所需磁盤扇區(qū)。而采用分頁技術(shù)的現(xiàn)代操作系統(tǒng)則利用請(qǐng)求頁面調(diào)度取得所需數(shù)據(jù)。
操作系統(tǒng)還有個(gè)頁的概念,其大小或者與基本內(nèi)存頁一致,或者是其倍數(shù)。典型的操作系統(tǒng)頁
從 2,048 到 8,192 字節(jié)不等,且始終是基本內(nèi)存頁大小的倍數(shù)。采用分頁技術(shù)的操作系統(tǒng)執(zhí)行 I/O 的全過程可總結(jié)為以下幾步:
- 確定請(qǐng)求的數(shù)據(jù)分布在文件系統(tǒng)的哪些頁(磁盤扇區(qū)組)。磁盤上的文件內(nèi)容和元數(shù)據(jù)可能跨越多個(gè)文件系統(tǒng)頁,而且這些頁可能也不連續(xù)。
- 在內(nèi)核空間分配足夠數(shù)量的內(nèi)存頁,以容納得到確定的文件系統(tǒng)頁。
- 在內(nèi)存頁與磁盤上的文件系統(tǒng)頁之間建立映射。
- 為每一個(gè)內(nèi)存頁產(chǎn)生頁錯(cuò)誤。
- 虛擬內(nèi)存系統(tǒng)俘獲頁錯(cuò)誤,安排頁面調(diào)入,從磁盤上讀取頁內(nèi)容,使頁有效。
- 一旦頁面調(diào)入操作完成,文件系統(tǒng)即對(duì)原始數(shù)據(jù)進(jìn)行解析,取得所需文件內(nèi)容或?qū)傩?信息。
需要注意的是,這些文件系統(tǒng)數(shù)據(jù)也會(huì)同其他內(nèi)存頁一樣得到高速緩存。對(duì)于隨后發(fā)生的 I/O
請(qǐng)求,文件數(shù)據(jù)的部分或全部可能仍舊位于物理內(nèi)存當(dāng)中,無需再從磁盤讀取即可重復(fù)使用。
大多數(shù)操作系統(tǒng)假設(shè)進(jìn)程會(huì)繼續(xù)讀取文件剩余部分,因而會(huì)預(yù)讀額外的文件系統(tǒng)頁。如果內(nèi)存
爭用情況不嚴(yán)重,這些文件系統(tǒng)頁可能在相當(dāng)長的時(shí)間內(nèi)繼續(xù)有效。這樣的話,當(dāng)稍后該文件又被相同或不同的進(jìn)程再次打開,可能根本無需訪問磁盤。這種情況您可能也碰到過:當(dāng)重復(fù)執(zhí)行類似的操作,如在幾個(gè)文件中進(jìn)行字符串檢索,第二遍運(yùn)行得似乎快多了。
類似的步驟在寫文件數(shù)據(jù)時(shí)也會(huì)采用。這時(shí),文件內(nèi)容的改變(通過 write( ))將導(dǎo)致文件系
統(tǒng)頁變臟,隨后通過頁面調(diào)出,與磁盤上的文件內(nèi)容保持同步。文件的創(chuàng)建方式是,先把文件映射到空閑文件系統(tǒng)頁,在隨后的寫操作中,再將文件系統(tǒng)頁刷新到磁盤。
內(nèi)存映射文件
傳統(tǒng)的文件 I/O 是通過用戶進(jìn)程發(fā)布 read( )和 write( )系統(tǒng)調(diào)用來傳輸數(shù)據(jù)的。為了在內(nèi)核空間的文件系統(tǒng)頁與用戶空間的內(nèi)存區(qū)之間移動(dòng)數(shù)據(jù),一次以上的拷貝操作幾乎總是免不了的。這是因?yàn)?,在文件系統(tǒng)頁與用戶緩沖區(qū)之間往往沒有一一對(duì)應(yīng)關(guān)系。但是,還有一種大多數(shù)操作系統(tǒng)都支持的特殊類型的 I/O 操作,允許用戶進(jìn)程最大限度地利用面向頁的系統(tǒng) I/O 特性,并完全摒棄緩沖區(qū)拷貝。這就是內(nèi)存映射 I/O,如圖 1-6 所示。
圖 1-6. 用戶內(nèi)存到文件系統(tǒng)頁的映射
內(nèi)存映射 I/O 使用文件系統(tǒng)建立從用戶空間直到可用文件系統(tǒng)頁的虛擬內(nèi)存映射。這樣做有幾個(gè)好處:
- 用戶進(jìn)程把文件數(shù)據(jù)當(dāng)作內(nèi)存,所以無需發(fā)布 read( )或 write( )系統(tǒng)調(diào)用。
- 當(dāng)用戶進(jìn)程碰觸到映射內(nèi)存空間,頁錯(cuò)誤會(huì)自動(dòng)產(chǎn)生,從而將文件數(shù)據(jù)從磁盤讀進(jìn)內(nèi)存。如果用戶修改了映射內(nèi)存空間,相關(guān)頁會(huì)自動(dòng)標(biāo)記為臟,隨后刷新到磁盤,文件得到更新。
- 操作系統(tǒng)的虛擬內(nèi)存子系統(tǒng)會(huì)對(duì)頁進(jìn)行智能高速緩存,自動(dòng)根據(jù)系統(tǒng)負(fù)載進(jìn)行內(nèi)存管理。
- 數(shù)據(jù)總是按頁對(duì)齊的,無需執(zhí)行緩沖區(qū)拷貝。
- 大型文件使用映射,無需耗費(fèi)大量內(nèi)存,即可進(jìn)行數(shù)據(jù)拷貝。
虛擬內(nèi)存和磁盤 I/O 是緊密關(guān)聯(lián)的,從很多方面看來,它們只是同一件事物的兩面。在處理大量數(shù)據(jù)時(shí),尤其要記得這一點(diǎn)。如果數(shù)據(jù)緩沖區(qū)是按頁對(duì)齊的,且大小是內(nèi)建頁大小的倍數(shù),那么,對(duì)大多數(shù)操作系統(tǒng)而言,其處理效率會(huì)大幅提升。
文件鎖定
文件鎖定機(jī)制允許一個(gè)進(jìn)程阻止其他進(jìn)程存取某文件,或限制其存取方式。通常的用途是控制共享信息的更新方式,或用于事務(wù)隔離。在控制多個(gè)實(shí)體并行訪問共同資源方面,文件鎖定是必不可少的。數(shù)據(jù)庫等復(fù)雜應(yīng)用嚴(yán)重信賴于文件鎖定。
“文件鎖定”從字面上看有鎖定整個(gè)文件的意思(通常的確是那樣),但鎖定往往可以發(fā)生在更為細(xì)微的層面,鎖定區(qū)域往往可以細(xì)致到單個(gè)字節(jié)。鎖定與特定文件相關(guān),開始于文件的某個(gè)特定字節(jié)地址,包含特定數(shù)量的連續(xù)字節(jié)。這對(duì)于協(xié)調(diào)多個(gè)進(jìn)程互不影響地訪問文件不同區(qū)域,是至關(guān)重要的。
文件鎖定有兩種方式:共享的和獨(dú)占的。多個(gè)共享鎖可同時(shí)對(duì)同一文件區(qū)域發(fā)生作用;獨(dú)占鎖則不同,它要求相關(guān)區(qū)域不能有其他鎖定在起作用。
共享鎖和獨(dú)占鎖的經(jīng)典應(yīng)用,是控制最初用于讀取的共享文件的更新。某個(gè)進(jìn)程要讀取文件, 會(huì)先取得該文件或該文件部分區(qū)域的共享鎖。第二個(gè)希望讀取相同文件區(qū)域的進(jìn)程也會(huì)請(qǐng)求共享 鎖。兩個(gè)進(jìn)程可以并行讀取,互不影響。但是,假如有第三個(gè)進(jìn)程要更新該文件,它會(huì)請(qǐng)求獨(dú)占 鎖。該進(jìn)程會(huì)處于阻滯狀態(tài),直到既有鎖定(共享的、獨(dú)占的)全部解除。一旦給予獨(dú)占鎖,其他共享鎖的讀取進(jìn)程會(huì)處于阻滯狀態(tài),直到獨(dú)占鎖解除。這樣,更新進(jìn)程可以更改文件,而其他讀取進(jìn)程不會(huì)因?yàn)槲募母牡玫角昂蟛灰恢碌慕Y(jié)果。圖 1-7 和圖 1-8 描述了這一過程。
文件鎖有建議使用和強(qiáng)制使用之分。建議型文件鎖會(huì)向提出請(qǐng)求的進(jìn)程提供當(dāng)前鎖定信息,但
操作系統(tǒng)并不要求一定這樣做,而是由相關(guān)進(jìn)程進(jìn)行協(xié)調(diào)并關(guān)注鎖定信息。多數(shù) Unix 和類Unix 操作系統(tǒng)使用建議型鎖,有些也使用強(qiáng)制型鎖或兼而有之。
強(qiáng)制型鎖由操作系統(tǒng)或文件系統(tǒng)強(qiáng)行實(shí)施,不管進(jìn)程對(duì)鎖的存在知道與否,都會(huì)阻止其對(duì)文件
鎖定區(qū)域的訪問。微軟的操作系統(tǒng)往往使用的是強(qiáng)制型鎖。假定所有文件鎖均為建議型,并在訪問共同資源的各個(gè)應(yīng)用程序間使用一致的文件鎖定,是明智之舉,也是唯一可行的跨平臺(tái)策略。依賴于強(qiáng)制文件鎖定的應(yīng)用程序,從根子上講就是不可移植的。
八、流I/O
并非所有 I/O 都像前面講的是面向塊的,也有流 I/O,其原理模仿了通道。 I/O 字節(jié)流必須順
序存取,常見的例子有 TTY(控制臺(tái))設(shè)備、打印機(jī)端口和網(wǎng)絡(luò)連接。
流的傳輸一般(也不必然如此)比塊設(shè)備慢,經(jīng)常用于間歇性輸入。多數(shù)操作系統(tǒng)允許把流置于非塊模式,這樣,進(jìn)程可以查看流上是否有輸入,即便當(dāng)時(shí)沒有也不影響它干別的。這樣一種能力使得進(jìn)程可以在有輸入的時(shí)候進(jìn)行處理, 輸入流閑置的時(shí)候執(zhí)行其他功能。
比非塊模式再進(jìn)一步,就是就緒性選擇。就緒性選擇與非塊模式類似(常常就是建立在非塊模
式之上),但是把查看流是否就緒的任務(wù)交給了操作系統(tǒng)。操作系統(tǒng)受命查看一系列流,并提醒進(jìn)程哪些流已經(jīng)就緒。這樣,僅僅憑借操作系統(tǒng)返回的就緒信息,進(jìn)程就可以使用相同代碼和單一線程,實(shí)現(xiàn)多活動(dòng)流的多路傳輸。這一技術(shù)廣泛用于網(wǎng)絡(luò)服務(wù)器領(lǐng)域,用來處理數(shù)量龐大的網(wǎng)絡(luò)連接。就緒性選擇在大容量縮放方面是必不可少的。








