1. 程式人生 > >儲存技術之卷管理和檔案系統

儲存技術之卷管理和檔案系統

轉自: http://segmentfault.com/blog/p_chou/1190000000698405

儲存技術如今已經越來越重要,而且在雲端計算時代,湧現出了很多專注於雲端儲存的廠商。儲存技術本身也十分複雜,從硬體到協議到軟體到介面幾乎覆蓋電腦科學的方方面面。筆者藉助《大話儲存II》這本書,開始了這塊知識空白的補充。本文的圖片均來源於網路。

卷管理(Volume Manager)

卷管理的原理

RAID在硬體層面提高了物理磁碟的效能、可靠性和利用率,它提供給上層作業系統虛擬的磁碟,在作業系統看來是物理磁碟。但是,隨之帶來的問題是,如果某塊虛擬的磁碟哪一天不夠用了怎麼辦?無法動態的新增容量。為了解決這個問題,在作業系統和RAID(或直接的磁碟控制器)之間產生了一種叫卷管理器(Volume Manager)的軟體。

卷管理器將RAID提交上來的磁碟進行再劃分和再重組,使得作業系統可以自由的對捲進行管理。為了理解卷管理,首先來看幾個概念:

  • PV(Physical Volume):即是RAID提交上來的虛擬磁碟(對於卷管理器而言它是物理磁碟),只是換個名詞,提交上來幾個虛擬磁碟就有幾個PV
  • PE(Physical Extends):將PV進行等大小劃分出來的物理區塊,每個PE都代表著PV上從幾號扇區到幾號扇區,PE是分割和合並的最小單位,可以在卷管理中設定
  • VG(Volume Group):卷管理器將PE進行組合,組成邏輯上的大的容器池,稱為VG
  • LV(Logical Volume):從VG中將若干數量的PE組合成邏輯卷。在Linux中,一個邏輯卷就可以被掛在到相應的目錄。

下面的圖可以說明上述的概念之間的關係:

卷管理通過劃分PE,將物理的磁碟分割,並進行再重組。這樣就可以在某個邏輯卷空間不足時將其他邏輯卷的PE搬一些過來使用。所以對於上層作業系統而言,邏輯卷是靈活多了。但是,這些關係是如此的繁雜,卷管理需要維護這些對應關係,所以需要在磁碟上儲存卷配置資訊,比如PE大小、初始偏移、PV的數量和資訊、排列順序等。儲存這個配置資訊的區域叫做VGDA(Volume Group Descriptor Area)。當卷管理器初始化時需要從VGDA上載入資訊,並生成對映公式,當上層系統發起IO請求時,卷管理器需要換算成實際磁碟及物理扇區位置(當然這些磁碟和物理扇區本身可能都是虛擬的),並通過驅動程式告知下層的控制器如何存取磁碟。

卷管理器甚至還具有軟RAID功能,可以將邏輯卷看成物理磁碟,組成RAID。

分割槽

分割槽實際上也可以看成一種簡單的卷管理,是作業系統自帶的卷管理程式,但是隻能管理單個磁碟,不能將多個磁碟組合成虛擬卷再劃分,不具備靈活的功能。我們通常見到的C:D:E:...盤就是通過分割槽得到的邏輯卷。作業系統可以針對分割槽(邏輯卷)進行格式化。

BIOS在進行引導時,總是會執行LBA1扇區上的指令,以載入作業系統,這個扇區稱為MBR(Master Boot Recorder),其中還儲存著分割槽表。通常第一條指令都是跳轉到活動分割槽讀取作業系統的程式碼並執行。在修改了分割槽設定的後,分割槽表會被更新。

卷管理程式同樣需要遵從BIOS和MBR,只不過它除了各個磁碟上寫入VGDA外,也要更新MBR中的分割槽表,劃分出一個小分割槽,將啟動作業系統的程式碼放在這個分割槽中,並表明bootable型別。在Linux中,這個分割槽就是/boot分割槽,其中包含有作業系統的啟動程式碼,大約只需要100MB。

BIOS執行的第一條指令位置總是LBA1,這是固定的。現在提出的新的EFI規範,可以配置第一條指令的所在扇區

在Linux中,每一個硬體裝置都對映到一個系統的檔案,對於硬碟、光碟機等 IDE 或 SCSI 裝置也不例外。Linux 把各種IDE裝置分配了一個由hd字首組成的檔案;而對於各種SCSI裝置,則分配了一個由sd字首組成的檔案。例如,第一個IDE裝置,Linux就定義為hda;第二個IDE裝置就定義為hdb;下面以此類推。而SCSI裝置就應該是sdasdb等。每一個硬碟裝置最多能有4個主分割槽(其中包含擴充套件分割槽)構成,任何一個擴充套件分割槽都要佔用一個主分割槽號碼,也就是在一個硬碟中,主分割槽和擴充套件分割槽一共最多是4個。主分割槽的作用就是計算機用來進行啟動作業系統的,因此每一個作業系統的載入程式,都應該存放在主分割槽上。擴充套件分割槽可以進一步劃分為邏輯分割槽。以第一個IDE硬碟為例說明,主分割槽(或者擴充套件分割槽)佔用了hda1hda2hda3hda4,而邏輯分割槽佔用了hda5hda16等12個號碼。因此,Linux下每一個硬碟總共最多有16個分割槽。下面是一個分割槽的例子:

從圖中我們解讀到如下資訊:

  • 上圖是一塊SCSI裝置硬碟,大小320G,被對映到/dev/sda
  • 劃分了一個主分割槽用於裝系統本身,大小41G左右,分割槽號1
  • 剩餘的空間劃分了一個邏輯分割槽,分割槽號2,5-10號的邏輯分割槽都是由這個擴充套件分區劃分出來的
  • 5-10是邏輯分割槽,有多種檔案系統型別

檔案系統

扇區是儲存的最小單位。然而,如果應用程式直接以扇區為單位進行存取,不但大大增加了複雜度,而且還增加了安全隱患。所以,需要由作業系統提供同一個管理介面,應用程式通過呼叫介面來完成資料的存取。也就是說,作業系統實際上就是在裸(Raw)裝置的基礎上,對磁碟進行邏輯上的結構化調整,並向上提供操作介面。這樣的東東就是檔案系統。檔案系統對磁碟不同的組織方式就形成了不同的檔案系統。例如FAT32NTFSEXT...

從磁碟的角度,讀寫的最小單位是扇區,但是如果讀取檔案都以扇區為單位的話,效率將是低下的。因為,扇區的只有512位元組,讀取較大體積的檔案將極大增加IO的次數。於是,有了邏輯塊的概念,也就是檔案系統中的最小儲存單元。一般,邏輯塊的大小為4KB,這樣比以扇區為單位讀寫資料要減少了8倍的IO數量。不過,由於邏輯塊是檔案系統的最小儲存單位,所以,如果儲存的檔案小於4KB,也必須佔用完整的4KB,因此,邏輯塊也不是越大越好,太大的話會導致空間利用率下降。

EXT2檔案系統

ext2檔案系統是Linux使用的預設檔案系統。在ext2檔案系統中,檔案的屬性和內容被分開存放。其中,檔案的屬性存放在inode中,而檔案的內容放在邏輯塊中。一個檔案有可能佔用一個或多個邏輯塊(block),但是一個檔案僅僅對應一個inode,下面介紹inode

  • inode好比檔案的索引,除了記錄檔案的屬性外,還要記錄檔案內容所在地邏輯塊號。因此,讀取檔案時必須從inode中得到檔案的塊號
  • inode本身大小有限,如果檔案比較大,inode的資料結構無法容納所有的邏輯塊號的話,就需要借用邏輯塊來存放
  • inode的數量決定了檔案的最大數量
  • 目錄也要佔用一個inode,一個目錄最少需要一個inode和一個block,在block中存放相關的檔案或目錄。因此如果要查詢一個目錄下的檔案,需要從根目錄的inode開始,一層層往下找

inode/block示意圖

較大的檔案需要動用block來記錄塊號

檔案系統的IO型別

檔案系統的IO型別分為同步IO非同步IO阻塞/非阻塞IO和Direct IO。這些分類不是同一層次的,需要分開討論:

對於應用程式而言,需要呼叫作業系統檔案系統的介面,這種介面可以分為同步IO和非同步IO:

  • 同步IO是指應用程式的執行緒發起IO請求後,會被作業系統掛起,直到IO完成後,重新喚醒執行緒並把結果告知執行緒。此時,執行緒會處於等待狀態,無法繼續執行。
  • 非同步IO是指作業系統不會掛起發起請求的執行緒,而是會繼續執行該執行緒,當IO完成後跑到執行緒的回撥函式中,以處理完成的IO結果。非同步IO下,執行緒得以繼續執行而不會等待。

阻塞/非阻塞IO是個廣義的概念,是指普遍意義上的上層程式向下層程式發起IO請求後是否等待下層程式:

  • 阻塞IO情況下上層程式會等待下層程式的返回才繼續執行後面的程式碼
  • 非阻塞IO情況下上層程式不會等待下層程式,而是繼續執行自己的程式碼,直到下層程式發起完成通知

同步IO是阻塞IO的一種,非同步IO是非阻塞IO的一種。

檔案系統具有自己的快取系統和快取演算法,以實現寫速度的提升和“預讀”。Direct IO就是告訴檔案系統不使用快取,而是直接將資料寫入磁碟。資料庫應用是使用Direct IO的典型應用,因為資料庫自己有實現一套資料快取和Flush演算法。比如Oracle甚至有獨立的程序DBWR來完成資料的Flush。