1. 程式人生 > >Linux下檔案的阻塞與非阻塞對部分系統呼叫的影響

Linux下檔案的阻塞與非阻塞對部分系統呼叫的影響

1.基本概念

所謂的阻塞,即核心在對檔案操作I/O系統呼叫時,如果條件不滿足(可能需要產生I/O),則核心會將該程序掛起。非阻塞則是發現條件不滿足就會立即返回。此外需要注意的是非阻塞並不是輪詢,不然就和阻塞沒多大區別了,它只是呼叫不成功就直接返回了,不會在去看啥時候會滿足條件,而是有你自己去選擇接下來該咋辦,系統以不再負責

2.read/write阻塞與非阻塞的理解

read/write系統呼叫,並不會去直接讀寫檔案,而只是去操作檔案所對應的記憶體頁(此時的頁為虛擬記憶體),對於read如果在頁中找到了想要讀寫的資料,則直接從頁中將資料copy到使用者快取即可,如果要讀的頁沒有找到,則只能從磁碟讀出該頁內容快取在記憶體中即可。所謂的讀過程,其實檔案系統所要做的只是鎖定頁面,然後構造一個讀請求,並將請求發給底層的IO子系統即可。linux核心中read系統呼叫預設是阻塞的write呼叫是非阻塞的,因為write時只是將使用者態的資料寫入快取頁面中即可返回

3.對於網路套接字阻塞/非阻塞對讀資料的影響

(1)在阻塞情況下

在阻塞條件下,read/recv/msgrcv的行為
1.如果沒有發現數據在網路緩衝中會一直等
2.當發現有資料時會把資料讀到使用者指定的快取區中(如果讀到的資料比指定的大小小,read此時並不會阻塞,而是會立即返回)

應為read的原則是在不超過指定長度的時候有多少讀多少,沒有資料就返回。所以一般情況下,如果我們想要讀取我們想要的位元組量,就得迴圈read

(2)在非阻塞情況下

在非阻塞情況下read的行為
1.如果發現沒有資料就直接返回
2.如果發現有資料,那麼也是採用有多少就讀多少,所以read完之後需要判斷是否再次進行read操作,以讀到我們想要的位元組數

對於讀的阻塞與非阻塞區別就在於沒有資料可讀時,是否立即返回

4.對於網路套接字阻塞/非阻塞對寫資料的影響

寫的操作本質也不是進行傳送操作,而是把使用者態的資料copy到系統底層去,然後由系統幫忙傳送。send,write返回成功,只表明資料已經copy到底層緩衝,而並不表明資料以傳送出去,更不能表示對方埠已經接收到資料

(1)阻塞情況下

write會將資料發完之後才返回,這裡與讀不同。當我們讀資料的時候,我們並不知道傳送端是否還有資料要發,如果一直等待就可能造成死迴圈,所以為了避免這類事情發生,我們把當前快取中的內容讀完,就返回了,並不關心是否讀夠了我們想要讀的位元組數。而write,由於需要寫的長度是知道的,所以它會一直寫夠指定的位元組才返回

(2)非阻塞情況下

非阻塞情況下,是採用可以寫多少就寫多少的策略,與讀不一樣的地方在於,有多少讀多少是由網路傳送端是否有資料傳輸到為標準。但是對於寫多少是由本地網路堵塞情況為標準的,對於非阻塞的情況就是一次寫多少算多少,有可能會造成部分寫入