筆記:磁盤分區、文件系統、連接

前言

我想要知道UNIX操做系統下closeunlink的區別,查閱了相關網絡資料和參考了《APUv3》寫下這篇記錄。html

我將從計算機磁盤分區開始寫起,一直UNIX操做系統的文件系統(主要指UFS:傳統的基於BSD的UNIX文件系統),而後辨明兩者區別。能夠直接跳至第三部分:《i結點和目錄項》查看。node

如下是本文的提綱:linux

  • 磁盤分區
  • 文件系統的構成是什麼?
  • i結點和目錄項是什麼?
  • 什麼是硬連接、符號連接?
  • openclose作了什麼?
  • unlink作了什麼?是否會刪除文件?

磁盤分區

基本單位:扇區

硬盤在出廠時要進行一次「低級格式化」,低級格式化的做用是把硬盤劃分紅扇區(sector)。
一個扇區指一個磁道上面固定大小(通常是512字節)的弧段,是物理上的最小獨立單位,是硬件被OS使用的最小的操做單元,就是一個扇區一個扇區進行操做(扇區的大小在存儲設備生產時就設計好)。shell

引導扇區

硬盤最開頭(編號最小)的扇區叫作引導扇區(bootsector)。
計算機開機後訪問硬盤時所必須要讀取的這個扇區,用於加載計算機操做系統,並轉讓處理器控制權給操做系統,因此引導扇區是不會劃分給分區的。數組

引導扇區的512個字節中:網絡

  • 有446個字節用來存放程序,這個程序的名字叫作(引導加載器)bootloader。這段程序負責啓動這個硬盤上某個分區裏面所安裝的操做系統。
  • 剩下的66個字節裏面有:數據結構

    • 64個字節用來作磁盤分區表(磁盤有多少個分區都在這裏面)。 64個字節的分區表裏面,每16個字節標識一個分區,因此一個硬盤最多能夠有四個主分區
    • 還有2個字節做爲引導扇區的結束代碼

扇區構成塊

塊(block)是邏輯上劃分的,一個塊由一個或多個扇區組成,是文件系統中的最小的操做單位(此處的「最小單位」,針對虛擬文件系統和具體文件系統分別指的是物理塊和邏輯塊)。oracle

塊能夠分爲物理塊和邏輯塊。函數

物理塊(虛擬文件系統操做的最小單位)

雖說是物理塊,它仍然是邏輯上劃分的。ui

操做系統的虛擬文件系統從硬件設備上讀取一個block,就是讀取了一個邏輯塊,實際是從硬件設備讀取一個或多個sector。
對於文件管理來講,每一個文件對應的多個block多是不連續的。block最終要映射到sector上,因此block的大小通常是sector的整數倍

物理塊的大小是可變化的,這取決於你在建立文件系統時的選擇。好比說,建立文件系統時,設置N個扇區組成一個物理塊,那麼每次操做系統的虛擬文件系統的I/O操做就會讀取一個虛擬塊到內存中。

虛擬文件系統:Linux支持的具體文件系統有:

  • 傳統文件系統:Ext二、ext三、ext四、Reiserfs(處理小文件)、Xfs、jfs
  • 光盤文件系統:ISO9660
  • 集羣文件系統:GFS(紅帽開發)、OCFS(oraclecluster fs)
  • 網絡文件系統:NFS、CIFS
  • Windows上的文件系統:VFAT(包括FAT、FAT32)、NTFS
  • USB文件系統:vfat

Linux把這些具體文件系統的差別屏蔽掉,構建了一個統一的虛擬文件系統(virtual file system,VFS),在用戶和基本文件系統之中加入了一層VFS,故在用戶看來Linux的文件系統只有VFS。

邏輯塊(具體文件系統操做的最小單位)

邏輯塊是相對於物理塊而言的。邏輯塊與物理塊的關係相似於虛擬內存中的頁與物理內存中的頁面的關係。

具體文件系統管理的是一個邏輯空間,這個邏輯空間就象一個大的數組,數組的每一個元素就是 具體文件系統 操做的基本單位——邏輯塊。

邏輯塊是從0開始編號的,並且,邏輯塊是連續的。與邏輯塊相對的是物理塊,物理塊是數據在磁盤上的存取單位,也就是每進行一次I/O操做,最小傳輸的數據大小。

只在須要進行I/O操做時才進行邏輯塊到物理塊的映射,這顯然避免了大量的I/O操做,於是文件系統可以變得高效。邏輯塊做爲一個抽象的概念,它必然要映射到具體的物理塊上去,所以,邏輯塊的大小必須是物理塊大小的整數倍,通常說來,二者是同樣大的。

分區

能夠把一個磁盤分紅多個分區。

計算機中最多能夠有4個主分區,可是咱們能夠在分區表(見第一部分的「引導扇區」)中拿出16字節,它不標識主分區,而是標識一個擴展分區。擴展分區能夠分紅N個邏輯分區。微軟通常這樣用,一個主分區(C盤),加一個擴展分區,由擴展分區再衍生出多個邏輯分區。Windows操做系統能夠裝在邏輯分區上。在這種狀況下計算機能夠有3個主分區,1個擴展分區。

擴展分區實際上 不是物理可用的分區,它僅僅是一個指向下一個分區的指針,這種指針結構將造成一個單向鏈表。
這樣在主引導扇區中除了主分區外, 僅須要存儲一個被稱爲擴展分區的分區數據,經過這個擴展分區的數據能夠找到下一個分區(實際上也就是下一個邏輯磁盤)的起始位置,以此起始位置類推能夠找到全部的分區。不管系統中創建多少個邏輯磁盤,在主引導扇區中經過一個擴展分區的參數就能夠逐個找到每個邏輯磁盤。

分區的創建

咱們在給新硬盤上創建分區時都要遵循如下的順序:創建主分區→創建擴展分區→創建邏輯分區→激活主分區→格式化全部分區
注意:

  1. 一個硬盤能夠有1到3個主分區和1個擴展分區,也能夠只有主分區而沒有擴展分區,但主分區必須至少有1個,擴展分區則最多隻有1個,且主分區+擴展分區總共不能超過4個。邏輯分區能夠有若干個。
  2. 分出主分區後,其他的部分能夠分紅擴展分區,通常是剩下的部分所有分紅擴展分區,也能夠不全分,剩下的部分就浪費了。
  3. 擴展分區不能直接使用,必須分紅若干邏輯分區。全部的邏輯分區都是擴展分區的一部分。 硬盤的容量=主分區的容量+擴展分區的容量擴展分區的容量=各個邏輯分區的容量之和
  4. 由主分區和邏輯分區構成的邏輯磁盤稱爲驅動器(Drive)或卷(Volume)。
  5. 激活的主分區會成爲「引導分區」(或稱爲「啓動分區」),引導分區會被操做系統和主板認定爲第一個邏輯磁盤(在DOS/Windows中會被識別爲「驅動器C:」或「本地磁盤C:」,即通稱的C盤)。有關DOS/Windows啓動的重要文件,如引導記錄、boot.inintldrntdetect.com等,必須放在引導分區中。
  6. DOS/Windows 中沒法看到非激活的主分區和擴展分區,但Windows 2000/Vista等NT內核的版本能夠在磁盤管理中查看全部的分區。

文件系統

每一個分區上能夠包含一個文件系統。
UNIX文件系統包括引導塊、超級塊、i節點區、文件存儲區(數據區)、進程對換區等。

  • 引導塊佔用第0號物理塊,不屬於文件系統管轄。若是系統中有多個文件系統,只有根文件系統纔有引導程序放在引導塊中,其他文件系統都不使用引導塊。
  • 超級塊佔用第1號物理塊,是文件系統的控制塊,超級塊包括:文件系統的大小、空閒塊數目、空閒塊索引表、空閒i節點數目、空閒i節點索引表、封鎖標記等。超級塊是文件系統爲文件分配存儲空間、回收存儲空間的依據。
  • i節點區存放i節點,i節點是對文件進行控制和管理的一種數據結構。
  • 文件存儲區是存放文件內容的區域,文件存儲區中各數據塊的使用狀況在超級塊中有記錄,系統利用超級塊中的記錄完成對數據塊的分配和回收。

i 結點

每個文件都由本身的i節點,每一個i節點都有惟一的i節點號。i結點保存了文件的屬性和類型、存放文件內容的物理塊地址、最近一次的存取時間、最後一次修改時間、建立此文件的時間。

i節點的結構以下(參考/usr/include/sys/ino.h

struct dinode
{
    ushort  di_mode; 
    short   di_nlink;
    ushort di_uid;
    ushort di_gid;
    off_t  di_size;
    char di_addr[40];
    time_t di_atime;
    time_t di_mtime;
    time_t di_ctime;
}

從上面的結構中能夠看出i節點中沒有記錄文件名字的。

事實上當咱們根據文件名查找文件時

  1. 在目錄塊中根據文件名能夠找到該文件所對應的i結點的編號
  2. 使用這個i結點編號咱們就能找到該文件所對應的i結點
  3. 這個結點中包含了文件的各類描述信息以及文件存在磁盤的什麼地方的指針
  4. 根據這個指針咱們就能獲得文件的數據內容

硬連接

顯然,在不一樣的目錄中,不一樣(或相同)的文件名能夠映射爲同一個i結點的編號,這意味着不一樣的文件名實際上能夠引用自同一個文件內容。

在i結點結構體定義中能夠找到short di_nlink;項,它就是連接計數,有多少個目錄項指向這個i結點,那麼它的di_nlink就是多少。和Java中的垃圾回收機制同樣,若是一個文件沒有任何目錄項引用它,即該文件不可能再被索引到,此時di_nlink==0這意味着文件能夠被刪除(也就是釋放文件內容所佔用的磁盤數據塊)。

這就是爲何「解除對一個文件的連接」不總意味着「釋放文件佔用的磁盤塊」,由於連接計數不爲0,說明還有其餘的目錄項引用了該文件。

這也是爲何刪除文件是unlink而不是'delete,由於沒有任何目錄項連接到該文件時,操做系統會自動釋放該文件所佔用的數據塊。

這種連接,就稱爲「硬連接」。

硬連接就是讓多個不在或者同在一個目錄下的文件名, 同時可以修改同一個文件,其中一個修改後,全部與其有硬連接的文件都一塊兒修改了。

值得一提的是目錄連接

目錄連接

一個目錄也能夠看做是一個文件,也就是說,目錄名映射爲一個i結點號,i節點號指向一個i結點,這個i結點有指針指向一個目錄數據塊,而這個目錄數據塊中就是目錄項數據,例如(文件名,i結點編號)(子目錄名,i結點編號)等記錄。

注意,子目錄中由於有指向父目錄的項(即..),所以父目錄中的每個子目錄都會使父目錄連接計數加1。

軟連接(符號連接)

符號連接(軟連接)是一類特殊的文件, 其包含有一條以絕對路徑或者相對路徑的形式指向其它文件或者目錄的引用。對符號連接文件進行讀寫的程序會表現得直接對目標文件進行操做。

也就是說,符號連接文件內容是目標文件的一個路徑,對符號連接文件操做,都會按照其中的路徑找到真正的目標文件,而後將操做施加上去。

一個符號連接文件僅包含有一個文本字符串,其被操做系統解釋爲一條指向另外一個文件或者目錄的路徑。
它是一個獨立文件,其存在並 不依賴於目標文件。
若是刪除一個符號連接,它指向的目標文件不受影響。
若是目標文件被移動、重命名或者刪除,任何指向它的符號連接仍然存在,可是它們將會指向一個不復存在的文件。這種狀況被有時被稱爲 被遺棄

opencloseunlink對連接數的影響

每個文件,均可以經過一個struct stat的結構體來得到文件信息,其中一個成員st_nlink表明文件的連接數。

  • 當經過shell的touch命令,或者在程序中open一個帶有O_CREAT不存在的文件時,文件的連接數爲1。
  • 一般open一個已存在的文件不會影響文件的連接數。open的做用只是使調用進程與文件之間創建一種 訪問關係 ,即open以後返回fd,調用進程能夠經過fdread write等等一系列對文件的操做。
  • close()就是 消除 這種調用進程與文件之間的訪問關係。天然,不會影響文件的連接數。
  • 在調用close時,內核會檢查打開該文件的進程數,若是此數爲0(沒有任何進程使用該文件),進一步檢查文件的連接數,若是這個數也爲0,那麼就刪除文件內容。
  • link函數建立一個新目錄項,而且 增長一個連接數
  • unlink函數 刪除目錄項 ,而且 減小一個連接數。若是連接數達到0而且沒有任何進程打開該文件,該文件內容才被真正刪除
  • 若是在unlilnk以前沒有close,那麼依舊能夠訪問文件內容。(也就是連接數爲0,可是仍然有進程在訪問。能夠想到此時若是close後,根據第4條,文件就會被真正刪除。)

綜上所訴:

  1. 真正影響連接數的操做是linkunlink以及open的建立。
  2. 刪除文件內容的真正含義是文件的連接數爲0,而這個操做的本質完成者是unlink
  3. 若是close可以實施刪除文件內容的操做,則一定是由於在close以前有一個unlink操做。

延伸閱讀

參考文獻

相關文章
相關標籤/搜索