Linux下磁盤的IO的各種機制

要說Linux下的IO過程,就要先說下Linux的地址空間問題,首先,Linux有一段虛擬內存,以32位x86系統爲例,虛擬內存爲2^32 即4G的內存空間,內核將這4G的空間分爲兩個部分,高位的1G字節(從虛地址0xC0000000到0xFFFFFFFF)供內核使用,稱爲“內核空間”。而較低的3G字節(從虛地址0x00000000到0xBFFFFFFF),供各個進程使用,稱爲“用戶空間”。因爲每個進程可以通過系統調用進入內核,因此,Linux內核空間由系統內的所有進程共享。於是,從具體進程的角度來看,每個進程可以擁有4G字節的虛擬地址空間(也叫虛擬內存)。(這裏順便提一下進程的上下文切換,當內核掛起一個進程,並儲存該進程當時在內存中所反映出的狀態或從內存中恢復下一個要執行的進程,恢復該進程原來的狀態到寄存器,返回到其上次暫停的執行代碼然後繼續執行。這個過程就會引起進程的上下文切換,進程上下文切換智能發生在內核態)

在經典IO過程中,會有一塊內核緩衝區和用戶緩衝區,內核緩衝區在內核空間,在內存中,用於內核程序,做爲讀自或寫往硬件的數據緩衝區,用戶緩衝區在用戶空間,在內存中,用於用戶程序,做爲讀自或寫往硬件的數據緩衝區。

在Linux下磁盤IO過程不是簡單的一個讀寫,傳統的IO方式,以read(),write()爲例,其實Linux內部完成了很多次數據拷貝,當我們要read(),write()一個fd的時候,首先要將數據從磁盤中拷貝到內核空間的頁緩存中,然後再將頁緩存的數據拷貝到用戶空間來,同理,write()一個fd的時候,也會將數據先寫入內核空間的頁緩存,然後再寫入磁盤,如下圖。


還有一種是同步IO方式,本質上與傳統IO方式沒有什麼不同,只是同步IO保證數據寫入磁盤後纔算IO過程完成,而傳統IO將數據寫入內核的高速緩衝區就算IO完成了


還有一種內存映射的IO方式,在Linux中,內存區域是可以跟一個普通的文件或設備文件的某一個部分關聯起來的,若進程要訪問內存頁中某個字節的數據,操作系統就會將訪問該內存區域的操作轉換爲相應的訪問文件的某個字節的操作。Linux提供了mmap()來實現這種文件方式。與標準的訪問文件的方式相比,內存映射方式可以減少標準訪問文件方式中 read() 系統調用所帶來的數據拷貝操作,即減少數據在用戶地址空間和操作系統內核地址空間之間的拷貝操作。映射通常適用於較大範圍,對於相同長度的數據來講,映射所帶來的開銷遠遠低於 CPU 拷貝所帶來的開銷。當大量數據需要傳輸的時候,採用內存映射方式去訪問文件會獲得比較好的效率


mmap()的作用是映射文件描述符和指定文件的(off_t off)區域至調用進程的(addr,addr *len)的內存區域,如下圖所示:



還有一種直接IO方式,凡是通過直接IO方式進行數據傳輸,數據均直接在用戶地址空間的緩衝區和磁盤之間直接進行傳輸,完全不需要頁緩存的支持。操作系統層提供的緩存往往會使應用程序在讀寫數據的時候獲得更好的性能,但是對於某些特殊的應用程序,比如說數據庫管理系統這類應用,他們更傾向於選擇他們自己的緩存機制,因爲數據庫管理系統往往比操作系統更瞭解數據庫中存放的數據,數據庫管理系統可以提供一種更加有效的緩存機制來提高數據庫中數據的存取性能。

                                       



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章