Linux 2.6 中提供的幾種文件訪問方式
所有的 I/O 操作都是通過讀文件或者寫文件來完成的。在這裡,我們把所有的外圍設備,包括鍵盤和顯示器,都看成是文件系統中的文件。訪問文件的方法多種多樣,這裡列出下邊這幾種 Linux 2.6 中支持的文件訪問方式。
標准訪問文件的方式
在 Linux 中,這種訪問文件的方式是通過兩個系統調用實現的:read() 和 write()。當應用程序調用 read() 系統調用讀取一塊數據的時候,如果該塊數據已經在內存中了,那麼就直接從內存中讀出該數據並返回給應用程序;如果該塊數據不在內存中,那麼數據會被從磁盤上讀到頁高緩存中去,然後再從頁緩存中拷貝到用戶地址空間中去。如果一個進程讀取某個文件,那麼其他進程就都不可以讀取或者更改該文件;對於寫數據操作來說,當一個進程調用了 write() 系統調用往某個文件中寫數據的時候,數據會先從用戶地址空間拷貝到操作系統內核地址空間的頁緩存中去,然後才被寫到磁盤上。但是對於這種標准的訪問文件的方式來說,在數據被寫到頁緩存中的時候,write() 系統調用就算執行完成,並不會等數據完全寫入到磁盤上。Linux 在這裡采用的是我們前邊提到的延遲寫機制( deferred writes )。
圖1.以標准方式對文件進行讀寫
同步訪問文件的方式
同步訪問文件的方式與上邊這種標准的訪問文件的方式比較類似,這兩種方法一個很關鍵的區別就是:同步訪問文件的時候,寫數據的操作是在數據完全被寫回磁盤上才算完成的;而標准訪問文件方式的寫數據操作是在數據被寫到頁高速緩沖存儲器中的時候就算執行完成了。
圖2.數據同步寫回磁盤
內存映射方式
在很多操作系統包括 Linux 中,內存區域( memory region )是可以跟一個普通的文件或者塊設備文件的某一個部分關聯起來的,若進程要訪問內存頁中某個字節的數據,操作系統就會將訪問該內存區域的操作轉換為相應的訪問文件的某個字節的操作。Linux 中提供了系統調用 mmap() 來實現這種文件訪問方式。與標准的訪問文件的方式相比,內存映射方式可以減少標准訪問文件方式中 read() 系統調用所帶來的數據拷貝操作,即減少數據在用戶地址空間和操作系統內核地址空間之間的拷貝操作。映射通常適用於較大范圍,對於相同長度的數據來講,映射所帶來的開銷遠遠低於 CPU 拷貝所帶來的開銷。當大量數據需要傳輸的時候,采用內存映射方式去訪問文件會獲得比較好的效率。
圖3.利用mmap代替read
本文URL地址:http://www.bianceng.cn/OS/Linux/201410/45415.htm
直接 I/O 方式
凡是通過直接 I/O 方式進行數據傳輸,數據均直接在用戶地址空間的緩沖區和磁盤之間直接進行傳輸,完全不需要頁緩存的支持。操作系統層提供的緩存往往會使應用程序在讀寫數據的時候獲得更好的性能,但是對於某些特殊的應用程序,比如說數據庫管理系統這類應用,他們更傾向於選擇他們自己的緩存機制,因為數據庫管理系統往往比操作系統更了解數據庫中存放的數據,數據庫管理系統可以提供一種更加有效的緩存機制來提高數據庫中數據的存取性能。
圖四.數據傳輸不經過操作系統內核緩沖區
異步訪問文件的方式
Linux 異步 I/O 是 Linux 2.6 中的一個標准特性,其本質思想就是進程發出數據傳輸請求之後,進程不會被阻塞,也不用等待任何操作完成,進程可以在數據傳輸的時候繼續執行其他的操作。相對於同步訪問文件的方式來說,異步訪問文件的方式可以提高應用程序的效率,並且提高系統資源利用率。直接 I/O 經常會和異步訪問文件的方式結合在一起使用。
圖5.CPU處理其他任務和I/O操作可以重疊進行