當前位置:編程學習大全網 - 源碼下載 - 第十四章 高級IO

第十四章 高級IO

fd是阻塞還是非阻塞是可以設置的,這也直接影響系統調用函數是否阻塞還是非阻塞(直接返回錯誤)

對於壹個給定的fd,有兩種方法可以指定為非阻塞IO

任意多個進程在壹個給定的字節上可以有壹把***享的讀鎖,但是在壹個給定字節上只能有壹個進程有壹把獨占寫鎖

單進程加寫鎖,後面的鎖範圍會覆蓋前面

F_SETLK 和 F_SETLKW 命令總是替換調用進程現有的鎖(若已存在),所以調用進程決不會阻塞在自己持有的鎖上,於是,F_GETLK 命令決不會報告調用進程自己持有的鎖

前面已經給出了 open、fork 以及 dup 調用後的數據結構(見圖 3-9 和圖 8-2)

在原來的這些圖上新加了 lockf 結構

建議性鎖:就是內核不去維護這個鎖,程序員自己要遵守這個原則

強制性鎖會讓內核檢查每壹個 open、read 和 write,驗證調用進程是否違背了正在訪問 的文件上的某壹把鎖。強制性鎖有時也稱為強迫方式鎖

從壹個fd讀,然後寫到另壹個fd,不去設置O_NOBLOCK,就會是阻塞IO,很常見

telnet命令結構:從終端讀(std-in),將數據寫到網絡連接上,同時從網絡連接讀,將所得數據寫到終端上(std-out),在網絡另壹端,telnetd守護進程讀用戶的命令,發送給shell,將shell執行的結果通過telnet命令發送給用戶,並顯示在終端上,如同登入了遠程機器了

telnet進程有兩個輸入,兩個輸出, 也就是兩個fd要去讀

終端用戶寫給telnet,網絡連接返回給telnet;telnet輸出給網絡連接,telnet輸出到終端給用戶

Ps: 將兩個輸入描述符都設置為非阻塞的,對第壹個描述符發壹個 read。如果該輸入上有數據,則 讀數據並處理它。如果無數據可讀,則該調用立即返回。然後對第二個描述符作同樣的處理。在 此之後,等待壹定的時間(可能是若幹秒),然後再嘗試從第壹個描述符讀。這種形式的循環稱 為 輪詢

這種方法的不足之處是浪費 CPU 時間。大多數時間實際上是無數據可讀,因此執行 read 系統調用浪費了時間

在每次循環後要等多長時間再執行下壹輪循環也很難確定

雖然輪詢技術 在支持非阻塞 I/O 的所有系統上都可使用,但是在多任務系統中應當避免使用這種方法

tvptr就是等待的時間

readfds

fd0 fd1 fd2

0 0 0 ...

writefds

exceptfds

這三個可以通過下面宏來操作fd,如果是null,表示不關心

maxfdpl:最大fd編號+1,在 3 個描述符集中找出最大描述符編號值,然後加 1

或者可以設置為FD_SETSIZE,最大值,通常是1024,但是壹般程序不會使用這麽多fd,通常3-10個,這樣內核就只需要在此範圍內尋找打開的位

比如 readset 有fd(0),fd(3);write有fd(1),fd(2)

那麽maxfdpl:4,也就是前四個位去尋找

maxfdp1壹樣

readfds,writefds,exceptfds壹樣

tsptr支持更加準確的時間,而且是const,pselect不能改變這個值

sigmask為了調用函數的時候可以安裝這個參數的屏蔽字,返回的時候再回復以前的屏蔽字

類似select,但是接口不同

沒有這個概念了:讀,寫,異常的fd集

pollfd:fd,感興趣的事件,已經發生的事件

nfds unsigned long

poll沒有修改events成員,與select不同,select修改參數來指示哪個fd已經準備好

與 select 壹樣,壹個描述符是否阻塞不會影響 poll 是否阻塞。有超時設置,而且就算壹個fd阻塞在那裏,只要其他fd準備好了,依舊可以返回

select和poll實現了異步通知

關於描述符的狀態,系統並 不主動告訴我們任何信息,我們需要進行查詢(調用 select 或 poll)

而前面提到的缺點,信號不夠,否則無法區分信號對應哪壹個fd

SUSv4 中將通用的異步 I/O 機制從實時擴展部分調整到基本規範部分。這種機制解決了這些 陳舊的異步 I/O 設施存在的局限性。

POSIX異步IO接口會有問題

System V 的異步 I/O 信號是 SIGPOLL

異步 I/O 是信號 SIGIO 和 SIGURG 的組合

這些異步 I/O 接口使用 AIO 控制塊來描述 I/O 操作

在進行異步 I/O 之前需要先初始化 AIO 控制塊,調用 aio_read 函數來進行異步讀操作,或 調用 aio_write 函數來進行異步寫操作

要想強制所有等待中的異步操作不等待而寫入持久化的存儲中,可以設立壹個 AIO 控制塊並 調用 aio_fsync 函數

如果 op 參數設定為 O_DSYNC,那麽操作執行起來就會像調用了 fdatasync 壹樣。否則,如果 op 參數設定為 O_SYNC, 那麽操作執行起來就會像調用了 fsync 壹樣

像 aio_read 和 aio_write 函數壹樣,在安排了同步時,aio_fsync 操作返回。在異步 同步操作完成之前,數據不會被持久化。AIO 控制塊控制我們如何被通知,就像 aio_read 和 aio_write 函數壹樣。為了獲知壹個異步讀、寫或者同步操作的完成狀態,需要調用 aio_error 函數

執行 I/O 操作時,如果還有其他事務要處理而不想被 I/O 操作阻塞,就可以使用異步 I/O。然 而,如果在完成了所有事務時,還有異步操作未完成時,可以調用 aio_suspend 函數來阻塞進 程,直到操作完成。

list 參數是壹個指向 AIO 控制塊數組的指針,nent 參數表明了數組中的條目數。數組中的空 指針會被跳過,其他條目都必須指向已用於初始化異步 I/O 操作的 AIO 控制塊

當還有我們不想再完成的等待中的異步 I/O 操作時,可以嘗試使用 aio_cancel 函數來取消它們

還有壹個函數也被包含在異步 I/O 接口當中,盡管它既能以同步的方式來使用,又能以異步的方 式來使用,這個函數就是 lio_listio。該函數提交壹系列由壹個 AIO 控制塊列表描述的 I/O 請求

readv 和 writev 函數用於在壹次函數調用中讀、寫多個非連續緩沖區。

散布讀(scatter read)和聚集寫(gather write)。

readn和writen

壹次 read 操作所返回的數據可能少於所要求的數據,即使還沒達到文件尾端也可能是 這樣。這不是壹個錯誤,應當繼續讀該設備

壹次 write 操作的返回值也可能少於指定輸出的字節數。這可能是由某個因素造成的, 例如,內核輸出緩沖區變滿

這兩 個函數只是按需多次調用 read 和 write 直至讀、寫了 N 字節數據

存儲映射 I/O(memory-mapped I/O)能將壹個磁盤文件映射到存儲空間中的壹個緩沖區上, 於是,當從緩沖區中取數據時,就相當於讀文件中的相應字節。與此類似,將數據存入緩沖區時, 相應字節就自動寫入文件

存儲映射 I/O 伴隨虛擬存儲系統已經用了很多年

為了使用這種功能,應首先告訴內核將壹個給定的文件映射到壹個存儲區域中

新程序則不能通過 exec 繼承存儲映射區,調用 mprotect 可以更改壹個現有映射的權限

如果***享映射中的頁已修改,那麽可以調用 msync 將該頁沖洗到被映射的文件中。msync 函數類似於 fsync(見 3.13 節),但作用於存儲映射區

當進程終止時,會自動解除存儲映射區的映射,或者直接調用 munmap 函數也可以解除映射區。

關閉映射存儲區時使用的文件描述符 並不解除映射區

對於 MAP_SHARED 區磁盤文件的更新,會在我們將數據寫到存儲映射區後的某個時刻, 按內核虛擬存儲算法自動進行。在存儲區解除映射後,對 MAP_PRIVATE 存儲區的修改會被丟棄

  • 上一篇:滾倉操作手法
  • 下一篇:橡膠網站源代碼
  • copyright 2024編程學習大全網