Linux文件系統詳解

Linux的一切皆文件

Linux 中的各類事物好比像文檔、目錄(Mac OS X 和 Windows 系統下稱之爲文件夾)、鍵盤、監視器、硬盤、可移動媒體設備、打印機、調制解調器、虛擬終端,還有進程間通訊(IPC)和網絡通訊等輸入/輸出資源都是定義在文件系統空間下的字節流。
一切均可看做是文件,其最顯著的好處是對於上面所列出的輸入/輸出資源,只須要相同的一套 Linux 工具、實用程序和 API。你可使用同一套api(read, write)和工具(cat , 重定向, 管道)來處理unix中大多數的資源.
設計一個系統的終極目標每每就是要找到原子操做,一旦鎖定了原子操做,設計工做就會變得簡單而有序。「文件」做爲一個抽象概念,其原子操做很是簡單,只有讀和寫,這無疑是一個很是好的模型。經過這個模型,API的設計能夠化繁爲簡,用戶可使用通用的方式去訪問任何資源,自有相應的中間件作好對底層的適配。
現代操做系統爲解決信息能獨立於進程以外被長期存儲引入了文件,文件做爲進程建立信息的邏輯單元可被多個進程併發使用。在 UNIX 系統中,操做系統爲磁盤上的文本與圖像、鼠標與鍵盤等輸入設備及網絡交互等 I/O 操做設計了一組通用 API,使他們被處理時都可統一使用字節流方式。換言之,UNIX 系統中除進程以外的一切皆是文件,而 Linux 保持了這一特性。爲了便於文件的管理,Linux 還引入了目錄(有時亦被稱爲文件夾)這一律念。目錄使文件可被分類管理,且目錄的引入使 Linux 的文件系統造成一個層級結構的目錄樹javascript

在Linux系統中,一切都是文件,理解文件系統,對於學習Linux來講,是一個很是有必要的前提html

Linux上的文件系統通常來講就是EXT2或EXT3,但這篇文章並不許備一上來就直接講它們,而但願結合Linux操做系統並從文件系統創建的基礎——硬盤開始,一步步認識Linux的文件系統。前端

1. 機械硬盤的物理存儲機制

  • 現代計算機大部分文件存儲功能都是由機械硬盤這種設備提供的。(如今的SSD和閃存從概念和邏輯上都部分繼承自機械硬盤,因此使用機械硬盤來進行理解也是沒有問題的)
  • 機械硬盤能實現信息存儲的功能基於:磁性存儲介質可以被磁化,且磁化後會長久保留被磁化的狀態,這種被磁化狀態可以被讀取出來,同時這種磁化狀態還可以不斷被修改,磁化正好有兩個方向,因此能夠表示0和1。
    因而硬盤就是把這種磁性存儲介質作成一個個盤片,每個盤片上都分佈着數量巨大的磁性存儲單位,使用磁性讀寫頭對盤片進行寫入和讀取(從原理上相似黑膠唱片的播放)。
  • 一個硬盤中的磁性存儲單位數以億計(1T硬盤就有約80億個),因此須要一套規則來規劃信息如何存取(好比一本存儲信息的書咱們還會分爲頁,每一頁從上到下從左到右讀取,同時還有章節目錄)
    因而就有了這些物理、邏輯概念:
  1. 一個硬盤有多張盤片疊成,不一樣盤片有編號
  2. 每張盤片上的存儲顆粒成環形一圈圈地排布,每一圈稱爲磁道,有編號
  3. 每條磁道上都有一圈存儲顆粒,每512*8(512字節,0.5KB)個存儲顆粒做爲一個扇區,扇區是硬盤上存儲的最小物理單位
  4. N個扇區能夠組成簇,N取決於不一樣的文件系統或是文件系統的配置,簇是此文件系統中的最小存儲單位
  5. 全部盤面上的同一磁道構成一個圓柱,稱爲柱面,柱面是系統分區的最小單位

磁頭讀寫文件的時候,首先是分區讀寫的,由inode編號(區內惟一的編號後面介紹)找到對應的磁道和扇區,而後一個柱面一個柱面地進行讀寫。機械硬盤的讀寫控制系統是一個使人歎爲觀止的精密工程(一個盤面上有幾億個存儲單位,每一個磁道寬度不到幾十納米,磁盤每分鐘上萬轉),同時關於讀寫的邏輯也是有諸多細節(好比扇區的編號並非連續的),很是有意思,能夠自行搜索文章拓展閱讀。java

有了硬盤並不意味着LInux能夠馬上把它用來存儲,還須要組合進Linux的文件體系才能被Linux使用。node

2.Linux文件體系

Linux以文件的形式對計算機中的數據和硬件資源進行管理,也就是完全的一切皆文件,反映在Linux的文件類型上就是:普通文件、目錄文件(也就是文件夾)、設備文件、連接文件、管道文件、套接字文件(數據通訊的接口)等等。而這些種類繁多的文件被Linux使用目錄樹進行管理, 所謂的目錄樹就是以根目錄(/)爲主,向下呈現分支狀的一種文件結構。不一樣於純粹的ext2之類的文件系統,我把它稱爲文件體系,一切皆文件和文件目錄樹的資源管理方式一塊兒構成了Linux的文件體系,讓Linux操做系統能夠方便使用系統資源。
因此文件系統比文件體系涵蓋的內容少不少,Linux文件體系主要在於把操做系統相關的東西用文件這個載體實現:文件系統掛載在操做系統上,操做系統整個系統又放在文件系統裏。但本文中文件體系的相關內容不是不少,大部分地方均可以用文件系統代替文件體系。linux

1. Linux中的文件類型:

1.1. 普通文件(-)

從Linux的角度來講,相似mp四、pdf、html這樣應用層面上的文件類型都屬於普通文件
Linux用戶能夠根據訪問權限對普通文件進行查看、更改和刪除編程

1.2. 目錄文件(d,directory file)

目錄文件對於用慣Windows的用戶來講不太容易理解,目錄也是文件的一種
目錄文件包含了各自目錄下的文件名和指向這些文件的指針,打開目錄事實上就是打開目錄文件,只要有訪問權限,你就能夠隨意訪問這些目錄下的文件(普通文件的執行權限就是目錄文件的訪問權限),可是隻有內核的進程可以修改它們
雖然不能修改,可是咱們可以經過vim去查看目錄文件的內容vim

這種類型的文件相似Windows中的快捷方式,是指向另外一個文件的間接指針,也就是咱們常說的軟連接api

1.4. 塊設備文件(b,block)和字符設備文件(c,char)

這些文件通常隱藏在/dev目錄下,在進行設備讀取和外設交互時會被使用到
好比磁盤光驅就是塊設備文件,串口設備則屬於字符設備文件
系統中的全部設備要麼是塊設備文件,要麼是字符設備文件,無一例外安全

1.5. FIFO(p,pipe)

管道文件主要用於進程間通信。好比使用mkfifo命令能夠建立一個FIFO文件,啓用一個進程A從FIFO文件裏讀數據,啓動進程B往FIFO裏寫數據,先進先出,隨寫隨讀。

1.6. 套接字(s,socket)

用於進程間的網絡通訊,也能夠用於本機之間的非網絡通訊
這些文件通常隱藏在/var/run目錄下,證實着相關進程的存在

Linux 的文件是沒有所謂的擴展名的,一個 Linux文件能不能被執行與它是否可執行的屬性有關,只要你的權限中有 x ,好比[ -rwx-r-xr-x ] 就表明這個文件能夠被執行,與文件名沒有關係。跟在 Windows下能被執行的文件擴展名一般是 .com .exe .bat 等不一樣。
不過,能夠被執行跟能夠執行成功不同。好比在 root 主目彔下的 install.log 是一個文本文件,修改權限成爲 -rwxrwxrwx 後這個文件可以真的執行成功嗎? 固然不行,由於它的內容根本就沒有能夠執行的數據。因此說,這個 x 表明這個文件具備可執行的能力, 可是能不能執行成功,固然就得要看該文件的內容了。
雖然如此,不過咱們仍然但願能從擴展名來了解該文件是什麼東西,因此通常咱們仍是會以適當的擴展名來表示該文件是什麼種類的。
因此Linux 系統上的文件名真的只是讓你瞭解該文件可能的用途而已, 真正的執行與否仍然須要權限的規範才行。好比常見的/bin/ls 這個顯示文件屬性的指令要是權限被修改成沒法執行,那麼ls 就變成不能執行了。這種問題最常發生在文件傳送的過程當中。例如你在網絡上下載一個可執行文件,可是恰恰在你的 Linux 系統中就是沒法執行,那就多是檔案的屬性被改變了。並且從網絡上傳送到你 的 Linux 系統中,文件的屬性權限確實是會被改變的

2. Linux目錄樹

對Linux系統和用戶來講,全部可操做的計算機資源都存在於目錄樹這個邏輯結構中,對計算機資源的訪問均可以認爲是目錄樹的訪問。就硬盤來講,全部對硬盤的訪問都變成了對目錄樹中某個節點也就是文件夾的訪問,訪問時不須要知道它是硬盤仍是硬盤中的文件夾。
目錄樹的邏輯結構也很是簡單,就是從根目錄(/)開始,不斷向下展開各級子目錄。

3.硬盤分區

硬盤分區是硬盤結合到文件體系的第一步,本質是「硬盤」這個物理概念轉換成「區」這個邏輯概念,爲下一步格式化作準備。
因此分自己並非必須的,你徹底能夠把一整塊硬盤做爲一個區。但從數據的安全性以及系統性能角度來看,分區仍是有不少用處的,因此通常都會對硬盤進行分區。

講分區就不得不先提每塊硬盤上最重要的第一扇區,這個扇區中有硬盤主引導記錄(Master boot record, MBR) 及分區表(partition table), 其中 MBR 佔有 446 bytes,而分區表佔有 64 bytes。硬盤主引導記錄放有最基本的引導加載程序,是系統開機啓動的關鍵環節,在附錄中有更詳細的說明。而分區表則跟分區有關,它記錄了硬盤分區的相關信息,但因分區表僅有 64bytes , 因此最多隻能記彔四塊分區(分區自己其實就是對分區表進行設置)。

只能分四個區實在太少了,因而就有了擴展分區的概念,既然第一個扇區所在的分區表只能記錄四條數據, 那我能否利用額外的扇區來記錄更多的分區信息。
把普通能夠訪問的分區稱爲主分區,擴展分區不一樣於主分區,它自己並無內容,它是爲進一步邏輯分區提供空間的。在某塊分區指定爲擴展分區後,就能夠對這塊擴展分區進一步分紅多個邏輯分區。操做系統規定:

  1. 四塊分區每塊均可以是主分區或擴展分區
  2. 擴展分區最多隻能有一個(也不必有多個)
  3. 擴展分區能夠進一步分割爲多個邏輯分區
  4. 擴展分區只是邏輯概念,自己不能被訪問,也就是不能被格式化後做爲數據訪問的分區,可以做爲數據訪問的分區只有主分區和邏輯分區
  5. 邏輯分區的數量依操做系統而不一樣,在 Linux 系統中,IDE 硬盤最多有 59 個邏輯分區(5 號到 63 號), SATA 硬盤則有 11 個邏輯分區(5 號到 15 號)
    通常給硬盤進行分區時,一個主分區一個擴展分區,而後把擴展分區劃分爲N個邏輯分區是最好的

是否能夠不要主分區呢?不知道,但好像不用管,你建立分區的時候會自動給你配置類型
特殊的,你最好單獨分一個swap區(內存置換空間),它獨爲一類,功能是:當有數據被存放在物理內存裏面,可是這些數據又不是常被 CPU 所取用時,那麼這些不常被使用的程序將會被丟到硬盤的 swap 置換空間當中, 而將速度較快的物理內存空間釋放出來給真正須要的程序使用

4.格式化

咱們知道Linux操做系統支持不少不一樣的文件系統,好比ext二、ext三、XFS、FAT等等,而Linux把對不一樣文件系統的訪問交給了VFS(虛擬文件系統),VFS能訪問和管理各類不一樣的文件系統。因此有了區以後就須要把它格式化成具體的文件系統以便VFS訪問。

標準的Linux文件系統Ext2是使用「基於inode的文件系統」

咱們知道通常操做系統的文件數據除了文件實際內容外, 還帶有不少屬性,例如 Linux 操做系統的文件權限(rwx)與文件屬性(擁有者、羣組、 時間參數等),文件系統一般會將屬性和實際內容這兩部分數據分別存放在不一樣的區塊
在基於inode的文件系統中,權限與屬性放置到 inode 中,實際數據放到 data block 區塊中,並且inode和data block都有編號
Ext2 文件系統在此基礎上

文件系統最前面有一個啓動扇區(boot sector)
這個啓動扇區能夠安裝開機管理程序, 這個設計讓咱們能將不一樣的引導裝載程序安裝到個別的文件系統前端,而不用覆蓋整個硬盤惟一的MBR, 也就是這樣才能實現多重引導的功能
把每一個區進一步分爲多個塊組 (block group),每一個塊組有獨立的inode/block體系
若是文件系統高達數百 GB 時,把全部的 inode 和block 統統放在一塊兒會由於 inode 和 block的數量太龐大,不容易管理
這其實很好理解,由於分區是用戶的分區,實際計算機管理時還有個最適合的大小,因而計算機會進一步的在分區中分塊
(但這樣豈不是可能出現大文件放不了的問題?有什麼機制善後嗎?)
每一個塊組實際還會分爲分爲6個部分,除了inode table 和 data block外還有4個附屬模塊,起到優化和完善系統性能的做用
因此整個分區大概會這樣劃分:

1. inode table

主要記錄文件的屬性以及該文件實際數據是放置在哪些block中,它記錄的信息至少有這些:
大小、真正內容的block號碼(一個或多個)
訪問模式(read/write/excute)
擁有者與羣組(owner/group)
各類時間:創建或狀態改變的時間、最近一次的讀取時間、最近修改的時間
沒有文件名!文件名在目錄的block中!
一個文件佔用一個 inode,每一個inode有編號
Linux 系統存在 inode 號被用完但磁盤空間還有剩餘的狀況
注意,這裏的文件不僅僅是普通文件,目錄文件也就是文件夾其實也是一個文件,還有其餘的也是
inode 的數量與大小在格式化時就已經固定了,每一個inode 大小均固定爲128 bytes (新的ext4 與xfs 可設定到256 bytes)
文件系統可以創建的文件數量與inode 的數量有關,存在空間還夠但inode不夠的狀況
系統讀取文件時須要先找到inode,並分析inode 所記錄的權限與使用者是否符合,若符合纔可以開始實際讀取 block 的內容
inode 要記錄的資料很是多,但恰恰又只有128bytes , 而inode 記錄一個block 號碼要花掉4byte ,假設我一個文件有400MB 且每一個block 爲4K 時, 那麼至少也要十萬條block 號碼的記錄!inode 哪有這麼多空間來存儲?爲此咱們的系統很聰明的將inode 記錄block 號碼的區域定義爲12個直接,一個間接, 一個雙間接與一個三間接記錄區(詳細見附錄)

2. data block

放置文件內容數據的地方
在格式化時block的大小就固定了,且每一個block都有編號,以方便inode的記錄
原則上,block 的大小與數量在格式化完就不可以再改變了(除非從新格式化)
在Ext2文件系統中所支持的block大小有1K, 2K及4K三種,因爲block大小的區別,會致使該文件系統可以支持的最大磁盤容量與最大單一文件容量各不相同:
Block 大小 1KB 2KB 4KB
最大單一檔案限制 16GB 256GB 2TB
最大檔案系統總容量 2TB 8TB 16TB
每一個block 內最多隻可以放置一個文件的資料,但一個文件能夠放在多個block中(大的話)
若文件小於block ,則該block 的剩餘容量就不可以再被使用了(磁盤空間會浪費)
因此若是你的檔案都很是小,可是你的block 在格式化時卻選用最大的4K 時,可能會產生容量的浪費
既然大的block 可能會產生較嚴重的磁碟容量浪費,那麼咱們是否就將block 大小定爲1K ?這也不妥,由於若是block 較小的話,那麼大型檔案將會佔用數量更多的block ,而inode 也要記錄更多的block 號碼,此時將可能致使檔案系統不良的讀寫效能
事實上如今的磁盤容量都太大了,因此通常都會選擇4K 的block 大小

3. superblock

記錄整個文件系統相關信息的地方,通常大小爲1024bytes,記錄的信息主要有:
block 與inode 的總量
未使用與已使用的inode / block 數量
一個valid bit 數值,若此文件系統已被掛載,則valid bit 爲0 ,若未被掛載,則valid bit 爲1
block 與inode 的大小 (block 爲1, 2, 4K,inode 爲128bytes 或256bytes);
其餘各類文件系統相關信息:filesystem 的掛載時間、最近一次寫入資料的時間、最近一次檢驗磁碟(fsck) 的時間
Superblock是很是重要的, 沒有Superblock ,就沒有這個文件系統了,所以若是superblock死掉了,你的文件系統可能就須要花費不少時間去挽救
每一個塊均可能含有superblock,可是咱們也說一個文件系統應該僅有一個superblock 而已,那是怎麼回事?事實上除了第一個塊內會含有superblock 以外,後續的塊不必定含有superblock,而若含有superblock則該superblock主要是作爲第一個塊內superblock的備份,這樣能夠進行superblock的救援

4. Filesystem Description

文件系統描述
這個區段能夠描述每一個block group的開始與結束的block號碼,以及說明每一個區段(superblock, bitmap, inodemap, data block)分別介於哪個block號碼之間

5. block bitmap

塊對照表
若是你想要新增文件時要使用哪一個block 來記錄呢?固然是選擇「空的block」來記錄。那你怎麼知道哪一個block 是空的?這就得要經過block bitmap了,它會記錄哪些block是空的,所以咱們的系統就可以很快速的找到可以使用的空間來記錄
一樣在你刪除某些文件時,那些文件本來佔用的block號碼就得要釋放出來, 此時在block bitmap 中對應該block號碼的標誌位就得要修改爲爲「未使用中」

6. inode bitmap

與block bitmap 是相似的功能,只是block bitmap 記錄的是使用與未使用的block 號碼, 至於inode bitmap 則是記錄使用與未使用的inode 號碼

5.掛載

在一個區被格式化爲一個文件系統以後,它就能夠被Linux操做系統使用了,只是這個時候Linux操做系統還找不到它,因此咱們還須要把這個文件系統「註冊」進Linux操做系統的文件體系裏,這個操做就叫「掛載」 (mount)。
掛載是利用一個目錄當成進入點(相似選一個現成的目錄做爲代理),將文件系統放置在該目錄下,也就是說,進入該目錄就能夠讀取該文件系統的內容,相似整個文件系統只是目錄樹的一個文件夾(目錄)。
這個進入點的目錄咱們稱爲「掛載點」。

因爲整個 Linux 系統最重要的是根目錄,所以根目錄必定須要掛載到某個分區。 而其餘的目錄則可依用戶本身的需求來給予掛載到不一樣的分去。

到這裏Linux的文件體系的構建過程其實已經大致講完了,總結一下就是:硬盤通過分區和格式化,每一個區都成爲了一個文件系統,掛載這個文件系統後就可讓Linux操做系統經過VFS訪問硬盤時跟訪問一個普通文件夾同樣。這裏經過一個在目錄樹中讀取文件的實際例子來細講一下目錄文件和普通文件。

6.目錄樹的讀取過程

首先咱們要知道

  1. 每一個文件(無論是通常文件仍是目錄文件)都會佔用一個inode
  2. 依據文件內容的大小來分配一個或多個block給該文件使用
  3. 建立一個文件後,文件完整信息分佈在3處地方,生成2個新文件:
    3.1 文件名記錄在該文件所在目錄的目錄文件的block中,沒有新文件生成
    3.2 文件屬性、權限信息、記錄具體內容的block編號記錄在inode中,inode是新生成文件
    3.3 文件具體內存記錄在block中,block是新生成文件
  4. 由於文件名的記錄是在目錄的block當中,「新增/刪除/改名文件名」與目錄的w權限有關
    因此在Linux/Unix中,文件名稱只是文件的一個屬性,叫別名也好,叫綽號也罷,僅爲了方便用戶記憶和使用,但系統內部並不須要用文件名來定爲文件位置,這樣處理最直觀的好處就是,你能夠對正在使用的文件更名,換目錄,甚至放到廢紙簍,都不會影響當前文件的使用,這在Windows裏是沒法想象的。好比你打開個Word文件,而後對其進行重命名操做,Windows會告訴你門兒都沒有,關閉文件先!但在Mac裏就毫無壓力,由於Mac的操做系統一樣採用了inode的設計。

建立文件過程

當在ext2下創建一個通常文件時, ext2 會分配一個inode 與相對於該文件大小的block 數量給該文件

  1. 例如:假設個人一個block 爲4 Kbytes ,而我要創建一個100 KBytes 的文件,那麼linux 將分配一個inode 與25 個block 來儲存該文件
  2. 但同時請注意,因爲inode 僅有12 個直接指向,所以還要多一個block 來做爲區塊號碼的記錄

建立目錄過程

當在ext2文件系統創建一個目錄時(就是新建了一個目錄文件),文件系統會分配一個inode與至少一塊block給該目錄

  1. inode記錄該目錄的相關權限與屬性,並記錄分配到的那塊block號碼
  2. 而block則是記錄在這個目錄下的文件名與該文件對應的inode號
  3. block中還會自動生成兩條記錄,一條是.文件夾記錄,inode指向自身,另外一條是..文件夾記錄,inode指向父文件夾

從目錄樹中讀取某個文件過程

  1. 由於文件名是記錄在目錄的block當中,所以當咱們要讀取某個文件時,就必定會通過目錄的inode與block ,而後纔可以找到那個待讀取文件的inode號碼,最終纔會讀到正確的文件的block內的資料。
  2. 因爲目錄樹是由根目錄開始,所以操做系統先經過掛載信息找到掛載點的inode號,由此獲得根目錄的inode內容,並依據該inode讀取根目錄的block信息,再一層一層的往下讀到正確的文件。
    舉例來講,若是我想要讀取/etc/passwd 這個文件時,系統是如何讀取的呢?
    先看一下這個文件以及有關路徑文件夾的信息:
1$ ll -di / /etc /etc/passwd
2     128 dr-xr-x r-x . 17 root root 4096 May 4 17:56 /
333595521 drwxr-x r-x . 131 root root 8192 Jun 17 00:20 /etc
436628004 -rw-r-- r-- . 1 root root 2092 Jun 17 00:20 /etc/passwd
複製代碼

因而該文件的讀取流程爲:

  1. /的inode:
    經過掛載點的信息找到inode號碼爲128的根目錄inode,且inode規定的權限讓咱們能夠讀取該block的內容(有r與x)
  2. /的block:
    通過上個步驟取得block的號碼,並找到該內容有etc/目錄的inode號碼(33595521)
  3. etc/的inode:
    讀取33595521號inode得知具備r與x的權限,所以能夠讀取etc/的block內容
  4. etc/的block:
    通過上個步驟取得block號碼,並找到該內容有passwd文件的inode號碼(36628004)
  5. passwd的inode:
    讀取36628004號inode得知具備r的權限,所以能夠讀取passwd的block內容
  6. passwd的block:
    最後將該block內容的資料讀出來
本文摘錄自:http://www.cnblogs.com/bellkosmos/p/detail_of_linux_file_system.html。

偶得一日閒,查閱Linux文件系統相關文章,偶然發現該文章,通讀全文後茅塞頓開,感嘆原文做者Linux之透徹,佩服至極,所以摘錄到本人公衆號內,稍加修整,以便廣大Linux愛好者閱讀。

以爲本文對你有幫助?請分享給更多人

關注「編程無界」,提高裝逼技能

相關文章
相關標籤/搜索