【Linux取經路】文件系統——inode與軟硬鏈接

在這里插入圖片描述

文章目錄

  • 一、前言
  • 二、認識硬件——磁盤
    • 2.1 磁盤的存儲構成
    • 2.2 磁盤的邏輯抽象
  • 三、操作系統對磁盤的使用
    • 3.1 再來理解創建文件
    • 3.2 再來理解刪除文件
    • 3.3 再來理解目錄
  • 四、硬鏈接
  • 五、軟鏈接
  • 六、結語

一、前言

在之前的【Linux取經路】文件系統之被打開的文件——文件描述符的引入一文中討論了被打開的文件,今天討論的話題則是沒有被打開的文件。文件等于文件內容文件屬性,沒打開的文件一定是存儲在磁盤上的,并且 Linux 是將文件的屬性和內容分開存儲文件內容以數據塊的形式進行存儲,文件屬性以 inode 的形式進行存儲

在這里插入圖片描述

二、認識硬件——磁盤

我們這里說的磁盤指的是機械磁盤,并非我們現在我們筆記本上使用的 SSD。機械磁盤是計算機上唯一的一個機械設備,也是一個外設。
在這里插入圖片描述
小Tips:磁頭是一面一個,磁頭與盤面不接觸。磁頭通過向盤面進行充放電來完成數據的寫入。磁盤叫做永久性存儲介質,內存叫做掉電易失性存儲介質。

2.1 磁盤的存儲構成

在這里插入圖片描述
每一個盤面由多個磁道構成,一個磁道又有多個扇區構成。磁盤被訪問的最基本單元是扇區,一般扇區的大小是 512 字節,有的是 4KB。要修改磁盤中 1 字節的數據,需要把該字節所在的扇區都加載到內存中。可以把磁盤看成是由無數個扇區構成的存儲介質。要把數據存儲到磁盤,第一個需要解決的問題就是如何定位一個扇區,首先需要定位盤面,也就是確定用哪個磁頭,因為一個磁頭對應一個盤面,接下來需要定位磁道,最后定位扇區。所有的磁頭都是同步運動的,在某一時刻,從從上向下看去,以磁頭所在點為半徑的不同盤面上的磁道就會形成一個叫做柱面的結構。磁頭運動主要是去定位磁道,盤面旋轉主要是去定位扇區,磁頭的定位是由硬件電路進行控制。由此可見,磁盤的讀取效率取決于磁頭、盤面的運動速度和運動次數,運動越少,效率越高;運動越多,效率越低。因此,在軟件設計上要求設計者一定要有意識的將相關數據放在一起。

2.2 磁盤的邏輯抽象

在這里插入圖片描述
最終一個磁盤可以看作是基于扇區的數組,每一個扇區都對應有一個下標來唯一標識。通過這個下標(LBA 邏輯扇區地址),再結合每一面磁道的個數和每一個磁道上扇區的個數就可以定位到該扇區在磁盤上的位置(CHS地址)。

小Tips:不僅 CPU 有寄存器,其它外設也有,磁盤中也有寄存器。比如:控制寄存器,用來存儲 CPU 下發的讀寫指令;數據寄存器,存儲要寫入的磁盤的數據;地址寄存器,存儲 CPU 傳送來的 LBA 地址;狀態寄存器,存儲磁盤的狀態,操作系統通過檢查該狀態寄存器去判斷讀寫是否成功。

三、操作系統對磁盤的使用

在這里插入圖片描述
上圖為 Linux ext2 磁盤文件系統圖(內核內存映像肯定有所不同),磁盤是典型的塊設備,操作系統首先會對磁盤進行分區,就如我們電腦中的 C 盤和 D 盤。接著,磁盤分區被劃分為若干個塊組(Block group),每個塊組中有許多塊(block),一個 block 的大小是由格式化的時候確定的,并且不可以更改,常見的是 4KB,即 4096字節。

  • Boot Block:通常存儲操作系統啟動的相關信息,比如:操作系統在什么位置、當前磁盤一共被劃分成了多少個分區等。這些信息一般存儲在磁盤的最前面,當然為了防止意外,這些內容在其它地方也會有備份。

  • Block Group:ext2 文件系統會根據分區的大小劃分為數個 Block Group。而每個 Block Group 都有著相同的結構組成。

  • Super Block:存放文件系統本身的信息,這里面記錄了整個分區的信息。例如:整個分區有多大、該分區里面每組的起始位置、每個組的大小、每個組的 inode 數量、每個組的 block 數量、每個組的其實 inode 編號、block 和 inode 的總量,未使用的 block 和 inode 的數量,一個 block 和 inode 的大小、文件系統的類型與名稱、最近一次掛載的時間、最近一次寫入數據的時間、最近一次檢驗磁盤的時間、該文件系統所擁有的字段以及字段的存儲順序和起始位置(也就是規定了一個組的空間劃分)等其它文件系統的相關信息。Super Block 的信息被破壞,可以說整個文件系統結構就被破壞了。該字段并不是在每一個分組中都有,而是在部分組里面有,防止意外發生,操作系統通過“魔數”來判斷是否是 Super Block。

  • Group Descriptor Table:塊組描述符,存儲塊組屬性信息,例如:當前分組的大小、使用情況、下一個文件描述符應該從哪開始。

  • Block Bitmap:塊位圖,將比特位的位置和塊號映射起來,里面記錄著 Data Block 中哪個數據塊已經被占用,哪個數據塊沒有被占用。

  • inode Bitmap:每個 bit 表示一個 inode 是否空閑可用。

  • inode Table:一組 inode。每一個 inode 用來存放單個文件的所有屬性,如:文件大小、所有者、最近修改時間等。每個 inode 的大小一般是 128字節,且每一個 inode 都有唯一的編號。一般而言,一個文件一個 inode。

  • Data block:數據區,存放文件內容。以塊的形式呈現,常見塊的大小是 4KB。每個塊都有自己獨一無二的塊號。

小Tips:操作系統在訪問磁盤的時候,會以塊為基本單位進行訪問。

格式化:每個組的前四個字段存儲的都是一些文件系統的屬性信息或者分組的使用情況信息,這些內容應該在我們使用磁盤之前都準備好。所以,每一個分區在被使用前,都必須將部分文件系統的屬性信息提前設置進對應的分區中,方便后續對分區和分組的使用,這個動作就叫做格式化。

在 Linux 中,文件的屬性里面是不包含文件的名稱在 Linux 系統里面標識文件用的是 inode 編號。一個 inode 表示一個文件的所有屬性,文件名并不屬于 inode 內的屬性。

在這里插入圖片描述
一個 inode 與 數據塊的對應關系:

在這里插入圖片描述
其中直接索引對應的塊中存儲的就是文件內容,二級索引對應的塊中存儲的不是文件內容而是塊號。假設塊的大小是 4KB,塊號用 4字節。那么一個塊就可以存儲 1024 個塊號,這 1024 個塊號對應的塊里面存儲的是文件的內容,三級索引同理。這樣做的目的是在 inode 里面用較少的空間就可以映射出更多的數據塊。

小Tips:inode 編號是以分區為單位進行統一分配的,而且不能跨分區,即每個分區中的 inode 編號都是從 0 開始,且一個分區中的 inode 個數是有上限的,因此可能會存在一下情況:一個分區中的 inode 被用完了,但是數據塊還沒有被用完,這種情況對應的就是創建了非常多的文件,但是每個文件的內容非常小;一個分區中的數據塊被用完了,但是 inode 還沒有被用完,這種情況就是創建的文件并不多,但是每個文件的大小非常大。

3.1 再來理解創建文件

首先創建文件一定是在一個路徑下(目錄)進行創建,這個路徑就會幫我們定位到一個分區,然后去從第一個分組開始查看當前分組的 GDT 字段,看該分組中 inode 的使用情況,若當前分組中的 inode 還有剩余,接著去讀取 inode_Bitmap,獲取最近一個未被使用的 inode 編號,然后拿著 inode 編號去 inode_Table 里面找到對應的 inode,將文件的屬性信息一填。如果有文件內容,先拿著 inode 編號找到對應的分組,根據寫入內容的大小去 Block_Bitmap 中找出對應數量未被使用的塊號,然后將這些塊號寫入到 inode 對應的屬性里面,然后拿著塊號去 Data blocks 中進行寫入。

3.2 再來理解刪除文件

刪除文件只要拿著該文件的 inode 編號,在 inode Table 中找到對應的 indoe,獲取到里面的 blocks,即拿到該文件對應的所有塊號,然后根據這些塊號將 Block Bitmap 中對應的比特位置0(假設 0 表示對應的塊未被使用)。最后再根據 inode 編號到 inode Bitmap 中將該 inode 對應的比特位置為0,至此,一個文件就被刪除啦。可以發現從頭到尾并沒有去修改塊中的內容,這也是為什么拷貝 4G 的文件很慢,刪 4G 的文件很快。所以在理論上,一個被刪除的文件,可以根據 inode 將其恢復出來。

總結:刪文件就是去修改 inode_Bitmap 和 Block_Bitmap 中的字段。在計算機領域的刪除并不等于清空,大部分情況下,刪除都表示可覆蓋。因為清空會導致效率大大下降。

3.3 再來理解目錄

上面說的所有對文件的操作都離不開 inode 編號,但是我們作為普通用戶平時好像也并沒有關注過 inode 編號,我們一般是直接使用文件名,此時就必須再來理解一下目錄了。目錄也是文件,也有自己的 inode,目錄也有屬性。目錄也有(數據塊),目錄的數據塊里面存放的是這個目錄下的所有文件名和該文件名對應的 inode 編號的映射關系,這是一種 key-value 結構,這就是為什么一個目錄里面不允許出現同名文件。與此同時,和目錄有關的一些歷史問題也得到了解決,對于一個目錄,沒有 w,我們無法在該目錄下創建文件,本質就是我們不能向目錄對應的數據塊中寫入文件名和 inode 的對應關系;沒有 r,無法產看該目錄下的文件,本質就是不能讀取目錄文件的數據塊。因此我們在查找一個文件時,首先需要知道該文件所在目錄的 inode,要知道目錄文件的 inode 編號,就需要知道目錄文件所在目錄的 inode 編號,如此遞歸一直到根目錄,這就是為什么我們在操作一個任何一個文件的時候都需要知道它的絕對或者相對路徑。如果每操作一個文件都要去這樣遞歸一層層的查找,那么效率是非常低的。因此在 Linux 操作系統中有一個叫做 dentry 緩存(目錄項緩存),里面記錄了該用戶經常訪問的文件名和 inode 編號之間的映射關系。

四、硬鏈接

// 創建硬鏈接的指令
ln test.txt hard-link

在這里插入圖片描述
硬連接不是一個獨立的文件,因為它沒有獨立的 inode。所謂建立硬連接,本質其實就是在特定目錄的數據塊中新增文件名和指向的文件的 inode 編號的映射關系。上圖也可以證明文件名不是 inode 中的屬性,因為一個 inode 編號對應一個 inode,如果文件名是 inode 中的屬性,那么上圖中編號 1978740 的文件不可能對應兩個文件名。

小Tips:任意一個文件,無論是目錄,還是普通文件,都有 inode,每一個 inode 內部,都有一個叫做引用計數的計數器,這個計數器記錄了有多少個文件名“指向”該文件(由硬鏈接可以得知,在 Linux 中可以讓多個文件名對應于同一個 inode)。完整的刪除文件過程就是先將特定目錄數據塊中的文件名與 inode 的映射關系刪除,然后根據 inode 的編號,將對應 inode 中的引用計數減減,最終看其是否減到零,減到零再執行 3.2 小結的步驟。此外,創建一個普通文件,它的硬鏈接數默認是1。

創建目錄文件的默認鏈接數為什么是 2 ?

在這里插入圖片描述
硬鏈接數為2,說明與該文件 inode 編號有關的映射關系有兩個,其中一個映射關系保存在 dir 所在目錄文件的數據塊,即 2023-11-06 目錄文件中的數據塊中,另外一個保存在 dir 目錄自身的數據塊中。

在這里插入圖片描述
根目錄的硬鏈接數減2就是根目錄下創建的目錄個數。根目錄稍微有一點特殊,根目錄中的 ... 文件名對應的 inode 編號是一樣的,都是根目錄。除去這倆文件名和 inode 編號的映射關系外,剩下的硬鏈接數就表示根目錄下創建的目錄個數,剩下的 18 個就是根目錄中所有目錄文件中 .. 與根目錄 inode 編號的鏈接關系。可以這樣計算的本質原因就是,根目錄下所有目錄中的 .. 都一定是指向根目錄的,對應根目錄的 inode 編號(也就是上圖中的 2 )。這種計算方法也可以推行到其它任意目錄。

總結:建立硬鏈接就是給一個已存在的文件創建別名,硬鏈接通常用來進行路徑定位,采用硬鏈接,可以進行目錄間切換。

在這里插入圖片描述
小Tips:Linux 系統不允許用戶對目錄文件建立硬連接。只要是為了避免在文件搜索的時候發生環路問題,系統在搜索文件的時候并不會搜索 ...,如果允許用戶為目錄文件創建硬鏈接,那么操作系統在進行文件搜索的時候就無法避免環路問題。

五、軟鏈接

// 創建軟鏈接的指令
ln -s file.txt soft-link

在這里插入圖片描述
軟鏈接是一個獨立的文件,有獨立的 inode,也有獨立的數據塊,它的數據塊里面存的是指向文件的路徑。軟鏈接非常像 Windows 中的快捷方式。軟鏈接的使用場景:一般發布的可執行程序可能存在一個較深的路徑下面,要執行它的話就需要帶很長一串路徑,顯得十分麻煩,此時我們就可以創建一個軟鏈接指向該可執行文件,之后要想運行該可執行程序就直接去執行軟鏈接即可。

在這里插入圖片描述
在這里插入圖片描述
小Tips:可以對任意類型的文件創建軟鏈接。

// 刪除軟硬鏈接都可以用 unlink 指令
unlink soft-link

六、結語

今天的分享到這里就結束啦!如果覺得文章還不錯的話,可以三連支持一下,春人的主頁還有很多有趣的文章,歡迎小伙伴們前去點評,您的支持就是春人前進的動力!

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/718620.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718620.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718620.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DevStack 基于 Ubuntu 部署 OpenStack

Devstack 簡介 DevStack 是一系列可擴展的腳本,用于基于 git master 的最新版本快速調出完整的 OpenStack 環境。devstack 以交互方式用作開發環境和 OpenStack 項目大部分功能測試的基礎。 devstack 透過執行 stack.sh 腳本,搭建 openstack 環境&…

AcWing 799. 最長連續不重復子序列

Problem: AcWing 799. 最長連續不重復子序列 文章目錄 思路解題方法復雜度Code 思路 這是一個求最長連續不重復子序列的問題。我們可以使用雙指針(滑動窗口)的方法來解決。我們維護一個窗口,并使用一個數組來記錄窗口內元素的出現次數。當窗口…

深度學習的一個完整過程通常包括以下幾個步驟

深度學習的一個完整過程通常包括以下幾個步驟: 問題定義和數據收集: 定義清晰的問題,明確任務的類型(分類、回歸、聚類等)以及預期的輸出。收集和整理用于訓練和評估模型的數據集。確保數據集的質量,進行預…

車聯網產品與應用

在中國,先是小鵬汽車官宣“智駕覆蓋城市數量、可用里程以及用戶口碑均為行業第一”。后有華為問界官宣OTA,領航功能全國可用路段高達99%,“全國都能用,哪哪都能開”。 似乎分分鐘,“自動駕駛”就要干成了。但日新月異的…

Day31|貪心算法1

貪心的本質是選擇每一階段的局部最優,從而達到全局最優。 無固定套路,舉不出反例,就可以試試貪心。 一般解題步驟: 1.將問題分解成若干子問題 2.找出適合的貪心策略 3.求解每一個子問題的最優解 4.將局部最優解堆疊成全局最…

【MySQL】深入解析 Buffer Pool 緩沖池

文章目錄 1、前置知識1.1、Buffer Pool介紹1.2、后臺線程1.2.1、Master Thread1.2.2、IO Thread1.2.3、Purge Thread1.2.4、Page Cleaner Thread 1.3、重做日志緩沖池 2、Buffer Pool 組成2.1、數據頁2.2、索引頁2.3、undo頁2.4、插入緩沖2.5、鎖空間2.6、數據字典2.6、自適應哈…

JavaScript之structuredClone現代深拷貝

在JavaScript中,實現深拷貝的方式有很多種,每種方式都有其優點和缺點。今天介紹一種原生JavaScript提供的structuredClone實現深拷貝。 下面列舉一些常見的方式,以及它們的代碼示例和優缺點: 1. 使用JSON.parse(JSON.stringify(…

代碼隨想錄 二叉樹第四周

目錄 617.合并二叉樹 700.二叉搜索樹中的搜索 98.驗證二叉搜索樹 530.二叉搜索樹的最小絕對差 501.二叉搜索樹中的眾樹 236.二叉樹的最近公共祖先 617.合并二叉樹 617. 合并二叉樹 簡單 給你兩棵二叉樹: root1 和 root2 。 想象一下,當你將其…

【Rust】——切片

🎃個人專欄: 🐬 算法設計與分析:算法設計與分析_IT閆的博客-CSDN博客 🐳Java基礎:Java基礎_IT閆的博客-CSDN博客 🐋c語言:c語言_IT閆的博客-CSDN博客 🐟MySQL&#xff1a…

第105講:Mycat垂直分表實戰:從規劃到解決問題的完整指南

文章目錄 1.垂直分表的背景2.垂直分表案例實戰2.1.垂直分表規劃2.2.配置Mycat實現垂直分表2.3.重啟Mycat2.4.在Mycat命令行中導入數據結構2.5.查看由Mycat分表后每個分片上存儲的表2.6.Mycat垂直分表后可能遇到的問題2.7.垂直分表完成 1.垂直分表的背景 我們的商城系統數據庫&…

Unity編輯器下如何獲取物體(GameObject)的中心位置

注意僅能在編輯器下才能使用該方法 實現方式依靠UnityEditor.Tools提供的參數,具體實現如下: 獲取單個物體的中心坐標 public static Vector3 GetGameObjectCenter(GameObject gameObject) {// 選中物體Selection.activeObject gameObject;// 記錄當前…

C#中Byte.Parse的用法,如果需要解析含有數字以外的字符,應該如何使用?

在C#中,Byte.Parse用于將字符串解析為byte類型的數字。它的用法如下: byte result Byte.Parse(str);其中,str是要解析的字符串。 如果要解析的字符串含有數字以外的字符,Byte.Parse會拋出一個FormatException異常。為了處理這種…

javaWebssh水利綜合信息管理系統myeclipse開發mysql數據庫MVC模式java編程計算機網頁設計

一、源碼特點 java ssh水利綜合信息管理系統是一套完善的web設計系統(系統采用ssh框架進行設計開發),對理解JSP java編程開發語言有幫助,系統具有完整的源代碼和數據庫,系統主要采用B/S模式開發。開發環境為TOMCA…

MATLAB 實現貝葉斯決策

1. 原理 后驗概率: 1.最小錯誤率決策(最大后驗概率決策): 2.最小風險決策: 3.正態分布下的貝葉斯決策 2. 過程 2.1 訓練集數據可視化 導入兩類訓練集數據,并繪制其數據分布,如下:…

云時代【5】—— LXC 與 容器

云時代【5】—— LXC 與 容器 三、LXC(一)基本介紹(二)相關 Linux 指令實戰:使用 LXC 操作容器 四、Docker(一)刪除、安裝、配置(二)鏡像倉庫1. 分類2. 相關指令&#xf…

JavaSE-09(Java IO精華總結)

Java IO 簡單做個總結: 1 .InputStream/OutputStream 字節流的抽象類。2 .Reader/Writer 字符流的抽象類。3 .FileInputStream/FileOutputStream 節點流:以字節為單位直接操作“文件”。4 .ByteArrayInputStream/ByteArrayOutputStream 節點流&#xff…

Running job: job_1709516801756_0003

** yarn運行卡在Running job: job_1709516801756_0003問題解決: ** 在運行wordcount時出現錯誤,一直卡住 運行命令:hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output 出現錯誤&#xff1a…

嶺回歸算法

回歸分析方法是利用數理統計方法分析數據,建立自變量和因變量間的回歸模型,用于預測因變量變化的分析方法。其中比較經典的是HoerI和Kennard提出的嶺回歸算法。嶺回歸算法是在最小二乘法的基礎上引|入正則項,使回歸模型具有較好泛化能力和穩定…

經典思路!人參葉際微生物如何發8分文章?

中國中醫科學院中藥研究所在《Environmental Microbiome》期刊上(IF7.9)發表了關于葉際真菌微生態網絡的文章,該研究通過對ITS測序結果和環境因子測定結果以及皂苷含量測定結果進行生信分析,提出了維持微生態網絡的穩定性策略和影響皂苷含量的因素。 期刊…

H12-821_113

113.如圖所示是路由器現ATE輸出的部分信息,以下關于這部分信息的描述,錯誤的是哪一項? A.display pim rp-info命令用來查看組播組對應的RP信息 B.RP地址是2.2.2.2 C.組地址是225.0.0.0 D.RP的優先級是0 答案:C 注釋: …