寫在前面
在開始正式的討論前,我先拋出幾個問題:
談到磁盤時,常說的HDD磁盤和SSD磁盤最大的區別是什么?這些差異會影響我們的系統設計嗎?
單線程寫文件有點慢,那多開幾個線程一起寫是不是可以加速呢?
write(2)函數成功返回了,數據就已經成功寫入磁盤了嗎?此時設備斷電會有影響嗎?會丟失數據嗎?
write(2)調用是原子的嗎?多線程寫文件是否要對文件加鎖?有沒有例外,比如O_APPEND方式?
坊間傳聞,mmap(2)的方式讀文件比傳統的方式要快,因為少一次拷貝。真是這樣嗎?為什么少一次拷貝?
如果你覺得這些問題都很簡單,都能很明確的回答上來。那么很遺憾這篇文章不是為你準備的,你可以關掉網頁去做其他更有意義的事情了。如果你覺得無法明確的回答這些問題,那么就耐心地讀完這篇文章,相信不會浪費你的時間。受限于個人時間和文章篇幅,部分議題如果我不能給出更好的解釋或者已有專業和嚴謹的資料,就只會給出相關的參考文獻的鏈接,請讀者自行參閱。
言歸正傳,我們的討論從存儲器的層次結構開始。
存儲器的金字塔結構
受限于存儲介質的存取速率和成本,現代計算機的存儲結構呈現為金字塔型[1]。越往塔頂,存取效率越高、但成本也越高,所以容量也就越小。得益于程序訪問的局部性原理[2],這種節省成本的做法也能取得不俗的運行效率。從存儲器的層次結構以及計算機對數據的處理方式來看,上層一般作為下層的Cache層來使用(廣義上的Cache)。比如寄存器緩存CPU Cache的數據,CPU Cache L1~L3層視具體實現彼此緩存或直接緩存內存的數據,而內存往往緩存來自本地磁盤的數據。
本文主要討論磁盤IO操作,故只聚焦于Local Disk的訪問特性和其與DRAM之間的數據交互。
無處不在的緩存
如圖,當程序調用各類文件操作函數后,用戶數據(User Data)到達磁盤(Disk)的流程如圖所示[3]。圖中描述了Linux下文件操作函數的層級關系和內存緩存層的存在位置。中間的黑色實線是用戶態和內核態的分界線。
從上往下分析這張圖,首先是C語言stdio庫定義的相關文件操作函數,這些都是用戶態實現的跨平臺封裝函數。stdio中實現的文件操作函數有自己的stdio buffer,這是在用戶態實現的緩存。此處使用緩存的原因很簡單——系統調用總是昂貴的。如果用戶代碼以較小的size不斷的讀或寫文件的話,stdio庫將多次的讀或者寫操作通過buffer進行聚合是可以提高程序運行效率的。stdio庫同時也支持fflush(3)函數來主動的刷新buffer,主動的調用底層的系統調用立即更新buffer里的數據。特別地,setbuf(3)函數可以對stdio庫的用戶態buffer進行設置,甚至取消buffer的使用。
系統調用的read(2)/write(2)和真實的磁盤讀寫之間也存在一層buffer,這里用術語Kernel buffer cache來指代這一層緩存。在Linux下,文件的緩存習慣性的稱之為Page Cache,而更低一級的設備的緩存稱之為Buffer Cache. 這兩個概念很容易混淆,這里簡單的介紹下概念上的區別:Page Cache用于緩存文件的內容,和文件系統比較相關。文件的內容需要映射到實際的物理磁盤,這種映射關系由文件系統來完成;Buffer Cache用于緩存存儲設備塊(比如磁盤扇區)的數據,而不關心是否有文件系統的存在(文件系統的元數據緩存在Buffer Cache中)。
綜上,既然討論Linux下的IO操作,自然是跳過stdio庫的用戶態這一堆東西,直接討論系統調用層面的概念了。對stdio庫的IO層有興趣的同學可以自行去了解。從上文的描述中也介紹了文件的內核級緩存是保存在文件系統的Page Cache中的。所以下篇的討論基本上是討論IO相關的系統調用和文件系統Page Cache的一些機制。
-
存儲器
+關注
關注
38文章
7637瀏覽量
166537 -
Linux
+關注
關注
87文章
11469瀏覽量
212908
原文標題:淺墨: 聊聊Linux IO(上)
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
VirtualLab Fusion案例:反射式金字塔波前傳感器的仿真
CADENAS 在 2025 年金字塔公司聯系博覽會上取得圓滿成功
基于金字塔模型的地形網格裂縫消除算法
可控特性的金字塔變換

一種金字塔注意力網絡,用于處理圖像語義分割問題

中國集成電路封裝行業市場現狀——金字塔的尖頂與基座
晶片表面刻蝕工藝對碳硅太陽能電池特性的影響

評論