文件系統----底層架構

當我們談到文件系統的時候,最重要的點在于:文件的內容與屬性是如何存儲在磁盤中的?以及操作系統是如何精準定位到這些文件內容的?在談及文件的內核前,我們先來了解一下儲存文件的硬件-----硬盤

一.理解硬件

首先我們來看一下傳統磁盤的基礎結構

磁盤是由磁頭,主軸,磁盤,磁頭臂,馬達組成的。類似于針一樣的就是磁頭,它可以左右移動;中間的圓盤就是主軸?,會帶動磁盤高速旋轉;空心圓就是磁盤,里面存儲了數據;磁頭臂控制磁盤的移動。

基于這種組成結構,那么磁盤是如何運轉的呢?

首先計算機只能對二進制進行識別,所以說磁盤當中的信息存儲就是用無數的0和1構成的。磁盤在高速旋轉中,磁頭與磁盤之間是有間距的并不是緊貼在磁盤上。磁盤通過順時針和逆時針的旋轉區別出0和1的信息,磁頭通過磁場感知將磁信號轉化成電信號。電信號再被傳輸到內存當中。

那么磁盤是如何存儲信息的,下面我們來看一下盤片的區域劃分的。

在硬盤中分為磁頭,磁道,扇區這三塊。如圖為三片六面,其中每一面都存在著一個磁頭,每個磁頭對應著相應的盤面,盤面以圓盤為中心向外存在著一圈一圈的稱為磁道,?每一圈磁道之間都有間隙,間隙與間隙之間的范圍稱為扇區。

在了解了上述三個概念之后,我們還要引入柱體這一概念。

?柱體是根據磁道來確定的,硬盤通常是由多片磁盤組成,有2片4片,每片都存在著上下磁頭,其中所有的磁頭都有機械軸串起來,所有磁頭與圓盤圓心的距離都是相同,這也就意味著,當1號磁頭停留在1號磁盤的1號磁道上,那么2號磁頭會在2號盤面上停留在1號磁道上,以此類推。該硬盤中這些磁道立體起來就變成了一個柱體。

那么我們應當如何定位硬盤中的任意位置?

我們先從物理結構來理解!

這里我們引入了“CHS定址法”。

通過上文講的柱體概念我們可以很輕松的理解。首先我們要先確定柱體的半徑大小,也就是磁道的編號,對應的(Cylinder)。接著確定柱體高度,也就是磁頭的編號,對應的(Header)。最后確認扇區的位置,對應的(Sector)。我們就完成了對硬盤的定位。類似于數學中的三維坐標,這里我們只是相應的更換了坐標系用“CHS”來進行定位。一個扇區大小通常為512字節,我們可以通過一個扇區大小來計算出硬盤的存儲量大小。

磁盤容量 = 磁頭數 * 磁道數 * 每條磁道扇區數 * 每扇區字節數

接下來我們從邏輯結構來理解!

我們用磁帶來類比一下。

?磁帶分為左右兩邊,左邊輸入右邊接收中間識別信息。我們將磁帶展開就是一條線性結構。

類比于硬盤,我們將同一條磁道上的每一個扇區劃分為一個單元格,我們對其展開,一條磁道上就是一條線性結構,我們可以將其類比于一個一維數組;而在同一個柱面上存在著許多類似的磁道,同樣的進行展開,就組成了一個面,我們將其類比于一個二維數組;整個硬盤由許多此類的柱面形成,我們想象成柱面卷成了一個更大的實心柱體,我們將其類比于一個三維數組。所以說,我們可以將硬盤簡單的理解成一個三維數組。

?一維磁道展開

?二維柱面展開

三維 柱面合成

?

?我們將硬盤類比于三維數組,通過數組下標我們便可以訪問到數組任意位置的信息,將下標信息轉化成CHS下標進行管理。

由于每個扇區大小較小,如果系統對一個扇區一個扇區進行管理對于操作系統來說消耗太頻繁。通常我們將八個扇區作為一組也就是4KB大小,我們將這八個扇區稱為“塊”。操作系統通過塊號來定位文件,從而屏蔽底層對于扇區的復雜定位,使得我們可以快速找到相應的扇區。

這里我們引入了“邏輯區塊地址” 也就是“LBA”(Logical Block Address)

我們將硬盤劃分為一個個塊,定義為區塊1,區塊2等等。意味著我們只要知道起始地址,磁盤的總大小,我們就可以定位到磁盤每個單位的下標,再通過CHS進行計算就可獲得對應的地址。因此,LBA尋址是對CHS尋址的邏輯抽象,LBA好似一個個門牌號而CHS更像是一間間確定的房間號,前者是對后者的簡化和升級。LBA尋址后也需要再轉換成CHS尋址確定位置。

二. 文件系統

我們整個磁盤有不同的大小之分,800GB,1TB等等,若操作系統在每次操作時都對整個磁盤進行掃描查找,必定會耗費大量的時間。結合我們的生活實際,通常我們會將一個大盤分為幾個小盤,C盤,D盤,F盤,這里就是采用了分治的思想。我們將各個區域分而治之,可以簡化管理提高我們操作的靈活性。

在類UNIX文件系統(如ext系列),完成分區之后,操作系統還會對每一個分區進行分組(Block Group)處理,將一個分區進行多個分組。每個組中會包含超級塊(Super Block),GDT(Group Description Table),塊位圖(Block Bitmap),inode位圖(inode Bitmap),inode表,數據區。

我們只要能弄清楚一個組中是如何工作的,根據分治的思想我們就能理解整個文件系統是如何運轉的。下面我們來理解一下上面的幾個概念。

超級塊:這是一個存儲整個文件結構信息的塊,類似于整個文件的地圖指南。主要記錄Block和inode的總量,使用情況,大小,最近一次掛載的時間,最近一次寫入數據的時間。若超級塊被破壞了,可以說整個文件系統結構就被破壞了。所以說,通常在每一個組中都會有一份超級塊進行備份,以免損壞后文件結構破壞。

GDT:塊組描述符,描述塊組的屬性信息。整個分區有多少個塊組就對應有多少個塊組描述符,記錄inode Table,Data Block的起始位置,空閑inode和Data數量,GDT在每個塊組開頭都有一份拷貝。

塊位圖:應用了位圖的方式用1表示該數據塊被占用,0表示未被占用。

inode位圖:表示inode是否空閑可用,對inode是否占用進行映射。

inode表:存放文件屬性的表。

數據區:存放文件內容的區域。

我們知道?文件 = 內容 + 屬性,文件內容被存放在數據區中,文件屬性被存放在inode表中,一個文件可以沒有內容,但是一定會有屬性。這里的inode相當于一個結構體,存儲著文件屬性,以及指向該文件數據區的指針。inode結構體中存在一個inode編號,使得操作系統可以定位區分不同的文件,inode結構體內又存在著數據區的指針,可以找到文件的內容,所以說,我們只要知道了inode編號我們就能得到文件的內容+屬性。

inode結構體:文件大小,文件所有者和所屬ID,文件類型權限,時間戳,指向文件數據塊的索引指針(雙重,三重指針)

?在知道inode號,我們如何對文件進行增刪查改?

增:遍歷inode位圖找到空閑的空間,分配數據塊,更新inode信息。

刪:通過inode號遍歷到inode,將inode位圖從0變為1。

查:用inode號找到inode表,判斷用戶權限大小,通過inode指針獲取數據塊內容。

改:定位inode并檢查權限,修改數據塊內容,最后更新inode表內容。

我們知道Linux下一切皆文件,同樣的目錄也是文件。inode里面不存文件名,文件名是存儲在目錄里的,我們在目錄下尋找文件,就是因為文件名與inode形成了一層映射關系。因此在同一個目錄下不能有兩個相同的文件名,因為不能有兩個相同的inode出現,所以說 文件名就是與inode對應。

對于一個文件的訪問權限,實際就是對于inode的訪問權限 ,inode會將權限信息存儲起來,即使對文件名進行刪除也不會影響到inode的訪問權限。

目錄名也是一個inode,它也有對應的數據塊。我們在目錄下尋找文件就是先從根目錄開始,向下尋找下一個目錄的inode,在目錄的inode中再向下尋找,以此類推。我們將這樣的過程稱為路徑解析,為了提高運行的效率。Linux內核中有dentry(directory entry)緩存,可以緩存近期解析的路徑信息,這樣可以減少操作系統的開銷。

下面我們通過一個完整詳細的流程來描述用戶程序中fwrite()寫入數據時,底層發生了什么,以及新文件的更新流程。

#include <stdio.h>
#include <stdlib.h>int main()
{FILE* fp = fopen("newfile.txt", "w");if (fp == NULL){perror("fopen");return 1;}const char* data = "Hello,fwrite!\n";size_t wrote = fwrite(data, 1, sizeof(data) - 1, fp);if (wrote < sizeof(data)){perror("data");return 1;}fclose(fp);return 0;
}

一. fopen階段

首先fopen()是C標準庫函數,不直接完成創建,它會調用系統調用(open())完成底層操作。fopen()根據"w"權限,會調用open(“newfile.txt”,O_WRONLY|O_CREAT|O_TRUNC,0666)。若文件不存在,傳入的O_CREAT就會創建一個新文件。

接著內核接收到open()的調用,會進行路徑解析。從根目錄開始查找文件所在目錄,通過dentry和inode表來找到該文件的inode。若該文件不存在,就要重新進行資源分配。

若文件不存在,那么就要為這一新創建的文件進行inode和Block的分配。先查找inode位圖,找到空閑的inode號,給新文件使用。在inode表中初始化該文件的屬性,此時不需要立即分配數據塊,數據塊將在后續寫入后進行分配。

此時內核需要對當前文件的目錄添加該文件的inode號,使目錄的數據塊對于inode號產生一個映射。

最后返回一個FILE*對象(struct file),并在進程中記錄。open()返回文件描述符fd,fopen()接受到fd后為其分配FILE*結構。

二. fwrite()階段

用戶將要輸入的信息用data保存并交給fwrite(),fwrite()將內容拷貝到用戶緩沖區中,此時并未真正輸入,當用戶調用fflush()或者緩沖區滿了,才會將數據刷入到系統當中。

當內容刷入到內核時,此時會進行系統調用write()。

先通過fd找到struct file對象,通過結構體找到對應的文件inode。此時需要檢查inode的數據塊指針,若未分配數據塊,此時先在數據位圖上找到一個空閑的位置進行分配,然后更新指針信息到inode結構體中。

將內容拷貝到緩沖區中,更新inode。

三. fclose階段

先調用fflush()將用戶緩沖區刷新,隨后調用系統close()關閉文件描述符,內核將減少file對象的引用計數,如果是最后一個關閉的將釋放file對象。inode和dentry會保存在緩存中一段時間方便下次尋找。

三. 軟硬鏈接?

我們通過 In? 【選項】? 源文件? ?目標文件? ? 來創建軟硬鏈接

若表示創建軟鏈接選項為? ?-s

1. 軟鏈接

當我們給一個文件添加軟鏈接時,會產生一個新的獨立文件,當然這個獨立文件也有自己的inode。

軟鏈接是對文件的一個拷貝,相當于我們計算機桌面的快捷方式一樣。

2. 硬鏈接?

硬鏈接是對文件inode進行拷貝,它沒有獨立的inode,它與源文件同用一個inode。當我們對一個文件進行硬鏈接時,會給該文件進行引用計數加一,當我們刪除了其中一個文件名時,引用計數相應的減一。由此我們可以知,硬鏈接是對文件進行備份處理

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

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

相關文章

小程序開發平臺,自主開發小程序源碼系統,多端適配,帶完整的部署教程

溫馨提示&#xff1a;文末有資源獲取方式全開源與自主開發源碼完全開放&#xff1a;開發者可自由修改前端界面、后端邏輯及數據庫結構&#xff0c;支持深度定制&#xff08;如調整用戶端交互流程、商家端管理功能等&#xff09;。技術棧透明&#xff1a;基于主流技術&#xff0…

stp拓撲變化分類

Max Age 20sHellotime 2sForward delay 153、拓撲改變需要多長時間1&#xff09;根橋故障&#xff1a;需要50秒&#xff08;Max age2個forwarding delay&#xff09;2&#xff09;非直連鏈路&#xff1a;非直連故障在穩定的STP網絡&#xff0c;非根橋會定期收到來自根橋的BPDU報…

一、深度學習——神經網絡

一、神經網絡 1.神經網絡定義&#xff1a;人工神經網絡&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;也簡稱為神經網絡&#xff08;NN&#xff09;&#xff0c;是一種模仿生物神經網絡結構和功能的計算模型。人腦可以看作是一個生物神經網絡&#xff0c;由…

【牛客算法】 小紅的奇偶抽取

文章目錄 一、題目介紹1.1 題目描述1.2 輸入描述1.3 輸出描述1.4 示例二、解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、解法實現3.1 解法一:字符串分離法3.1.1 初級版本分析3.2 解法二:數學逐位構建法(推薦)3.2.1 優化版本分析四、總結與拓展4.1 關鍵優化技…

Maven 繼承:構建高效項目結構的利器

一、引言 Maven 是一個強大的項目管理工具&#xff0c;它通過標準化的項目結構和依賴管理極大地簡化了 Java 項目的開發流程。在 Maven 中&#xff0c;繼承是一種非常有用的功能&#xff0c;它允許我們創建一個父項目&#xff0c;其他子項目可以繼承這個父項目的配置信息&#…

Mysql組合索引的update在多種情況下的間隙鎖的范圍(簡單來說)

簡單來說&#xff0c;當 UPDATE 語句的 WHERE 條件使用了組合索引&#xff0c;并且需要鎖定不存在的“間隙”來防止幻讀時&#xff0c;就會產生間隙鎖。間隙鎖的范圍取決于 WHERE 條件如何利用組合索引&#xff0c;以及數據庫的隔離級別。 我們用圖書館的例子。比如&#xff1a…

什么是Apache Ignite的affinity(親和性)

在 Apache Ignite 中&#xff0c; affinity&#xff08;親和性&#xff09; 是一種用于控制數據分布和查詢性能的重要機制。它允許開發者指定數據如何在集群中的節點之間分布&#xff0c;從而優化數據訪問和查詢效率。以下是關于 affinity 的詳細解釋&#xff1a;數據親和性&a…

youtube圖論

dfs排序lifo & fifo存儲方式鄰接矩陣dijstra處理過的保存/更新&#xff0c;意味著一個節點避免了重復訪問bfs dfs

借助ssh實現web服務的安全驗證

背景 公有云服務器 http 服務 80端口&#xff0c;想做到安全訪問無須HTTPS 客戶端證書方便、快捷、安全 SSH 隧道 本地代理 使用 SSH 隧道將 HTTP 服務“隱藏”在 SSH 之后&#xff1a; # 客戶端建立隧道&#xff08;將本地 8080 轉發到服務器的 80 端口&#xff09; ssh…

狀態機在前端開發中的藝術:從理論到框架級實踐

文章目錄一 狀態機&#xff1a;復雜邏輯的終結者1.1 什么是狀態機&#xff1f;1.2 為何前端需要狀態機&#xff1f;二 狀態機核心概念深度解析2.1 有限狀態機&#xff08;FSM&#xff09;與分層狀態機&#xff08;HSM&#xff09;2.2 狀態機的數學表示三 前端開發中的狀態機實戰…

把word中表格轉成excle文件

把word中表格轉成excle文件 from docx import Document from openpyxl import Workbook from pathlib import Path# 打開 Word 文檔 document Document(./weather_report.docx) tables document.tables# 輸出文件路徑 output_file Path(./weather_report.xlsx)# 如果文件已存…

運維打鐵: 阿里云 ECS 實例的高效運維與管理

文章目錄思維導圖正文內容一、實例基礎管理1. 實例創建2. 實例配置調整3. 實例停止與啟動二、性能監控與優化1. 系統性能指標監控2. 磁盤 I/O 優化3. 網絡優化三、安全防護1. 防火墻設置2. 賬號安全管理3. 數據備份與恢復四、自動化運維1. 腳本自動化2. 使用云助手五、成本優化…

RV1126平臺(Buildroot Linux)+ SunplusIT SPCA2688 USB攝像頭 RTSP推流全流程復盤與問題解決記錄

# RK RV1126平臺&#xff08;Buildroot Linux&#xff09; SunplusIT SPCA2688 USB攝像頭 RTSP推流全流程復盤與問題解決記錄一、平臺與需求- **硬件平臺**&#xff1a;Rockchip RV1126 - **操作系統**&#xff1a;基于Buildroot定制的Linux系統 - **USB攝像頭**&#xff1a;Su…

深入理解Java虛擬機:Java內存區域與內存溢出異常

前言Java虛擬機&#xff08;JVM&#xff09;的自動內存管理是其核心特性之一&#xff0c;它極大地簡化了開發者的工作&#xff0c;減少了內存泄漏和內存溢出的問題。本文將詳細介紹JVM的自動內存管理機制的內存區域與內存溢出異常問題&#xff0c;包括運行時數據區域、對象的創…

位圖入門算法191. 位1的個數

題目鏈接&#xff1a; 191. 位1的個數 - 力扣&#xff08;LeetCode&#xff09; 這道題讓我們找出一個數字中二進制中1的個數&#xff0c;這個題目我們就用1的&來解決&#xff0c;最后一位有0為0&#xff0c;都是1才是1&#xff0c;我們只需要判斷32次即可。 代碼如下&am…

[架構之美]虛擬機Ubuntu密碼重置

[架構之美]虛擬機Ubuntu密碼重置 當您在虛擬機中運行Ubuntu系統時&#xff0c;忘記密碼不再意味著數據丟失&#xff01;本文將詳細介紹可靠的密碼重置方法&#xff0c;幫助您快速恢復系統訪問權限。 一、虛擬機密碼重置原理與準備 1.1 為什么虛擬機重置密碼更容易 在虛擬機環…

kotlin中withContext,async,launch幾種異步的區別

在 Kotlin 協程中&#xff0c;withContext、async 和 launch 是常用的異步/并發操作函數&#xff0c;它們的主要區別在于用途和返回值&#xff1a;1. launch 作用&#xff1a;啟動一個新的協程&#xff0c;用于執行不返回結果的并發任務。使用場景&#xff1a;適合執行沒有返回…

git 報錯fatal: refusing to merge unrelated histories

解決方案在你操作命令后面加--allow-unrelated-histories 例如&#xff1a; git merge master --allow-unrelated-historiesgit pull或者git push報fatal: refusing to merge unrelated histories 同理&#xff1a; git pull origin master --allow-unrelated-histories

Android 13----在framworks層映射一個物理按鍵

基于Android 13.一、映射步驟確定要映射的物理按鍵值在kl文件中增加鍵值對在InputEventLabels.cpp增加AKEYCODE在keycodes.h中定義AKEYCODE值attrs.xml中增加KEYCODEKeyEvent.java中增加KEYCODE在PhoneManagerWindow等相關類中進行攔截處理相關KEYCODE&#xff0c;屬于具體的業…

【Java EE】Mybatis-Plus

1. 開始先進行和以前一樣的項目配置、數據庫連接配置&#xff0c;在這些基礎上&#xff0c;額外引入 Mybatis-Plus 依賴即可。<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><vers…