從品牌網站建設到網絡營銷策劃,從策略到執(zhí)行的一站式服務
來源:公司資訊 | 2021.08.19
和 CPU、內存相同,磁盤和文件體系的辦理,也是操作體系最核心的功能。
磁盤為體系供給了最基本的持久化存儲。
文件體系則在磁盤的基礎上,供給了一個用來辦理文件的樹狀結構。
那么,磁盤和文件體系是怎么作業(yè)的呢?又有哪些目標能夠衡量它們的功能呢?
索引節(jié)點和目錄項
文件體系,本身是對存儲設備上的文件,進行安排辦理的機制。安排方法不同,就會構成不同的文件體系。
咱們要記住最重要的一點,在 Linux 中一切皆文件。不只普通的文件和目錄,就連塊設備、 套接字、管道等,也都要經過一致的文件體系來辦理。
為了方便辦理,Linux 文件體系為每個文件都分配兩個數(shù)據(jù)結構,索引節(jié)點(index node)和目錄項(directory entry)。它們首要用來記載文件的元信息和目錄結構。
索引節(jié)點,簡稱為 inode,用來記載文件的元數(shù)據(jù),比方 inode 編號、文件巨細、拜訪 權限、修正日期、數(shù)據(jù)的位置等。索引節(jié)點和文件一一對應,它跟文件內容相同,都會 被持久化存儲到磁盤中。所以記住,索引節(jié)點同樣占用磁盤空間。
目錄項,簡稱為 dentry,用來記載文件的名字、索引節(jié)點指針以及與其他目錄項的相關 聯(lián)系。多個相關的目錄項,就構成了文件體系的目錄結構。不過,不同于索引節(jié)點,目錄項是由內核保護的一個內存數(shù)據(jù)結構,所以一般也被叫做目錄項緩存。
換句話說,索引節(jié)點是每個文件的唯一標志,而目錄項保護的正是文件體系的樹狀結構。目錄項和索引節(jié)點的聯(lián)系是多對一,你能夠簡單了解為,一個文件能夠有多個別號。
舉個比方,經過硬鏈接為文件創(chuàng)建的別號,就會對應不同的目錄項,不過這些目錄項本質上仍是鏈接同一個文件,所以,它們的索引節(jié)點相同。
索引節(jié)點和目錄項紀錄了文件的元數(shù)據(jù),以及文件間的目錄聯(lián)系,那么具體來說,文件數(shù)據(jù)到底是怎么存儲的呢?是不是直接寫到磁盤中就好了呢?
實際上,磁盤讀寫的最小單位是扇區(qū),然而扇區(qū)只要 512B 巨細,假如每次都讀寫這么小的單位,功率必定很低。所以,文件體系又把接連的扇區(qū)組成了邏輯塊,然后每次都以邏 輯塊為最小單元,來辦理數(shù)據(jù)。常見的邏輯塊巨細為 4KB,也便是由接連的 8 個扇區(qū)組成。
為了協(xié)助咱們了解目錄項、索引節(jié)點以及文件數(shù)據(jù)的聯(lián)系,畫了一張示意圖。咱們能夠對照著這張圖,來回憶剛剛講過的內容,把知識和細節(jié)串聯(lián)起來。
不過,這里有兩點需要咱們注意:
榜首,目錄項本身便是一個內存緩存,而索引節(jié)點則是存儲在磁盤中的數(shù)據(jù)。在前面的 Buffer 和 Cache 原理中,我從前提到過,為了協(xié)調慢速磁盤與快速 CPU 的功能差異,文 件內容會緩存到頁緩存 Cache 中。那么,咱們也應該想到,這些索引節(jié)點天然也會緩存到內存中,加快文件的拜訪。
第二,磁盤在履行文件體系格式化時,會被分紅三個存儲區(qū)域,超級塊、索引節(jié)點區(qū)和數(shù)
據(jù)塊區(qū)。其間,
超級塊,存儲整個文件體系的狀態(tài)。
索引節(jié)點區(qū),用來存儲索引節(jié)點。
數(shù)據(jù)塊區(qū),則用來存儲文件數(shù)據(jù)。
虛擬文件體系
目錄項、索引節(jié)點、邏輯塊以及超級塊,構成了 Linux 文件體系的四大基本要素。不過, 為了支撐各種不同的文件體系,Linux 內核在用戶進程和文件體系的中心,又引入了一個籠統(tǒng)層,也便是虛擬文件體系 VFS(Virtual File System)。
VFS 定義了一組一切文件體系都支撐的數(shù)據(jù)結構和規(guī)范接口。這樣,用戶進程和內核中的其他子體系,只需要跟 VFS 供給的一致接口進行交互就能夠了,而不需要再關心底層各種文件體系的完結細節(jié)。
這里,下圖是 Linux 文件體系的架構圖,幫咱們更好地了解體系調用、VFS、緩存、文 件體系以及塊存儲之間的聯(lián)系。
經過這張圖,能夠看到,在 VFS 的下方,Linux 支撐各種各樣的文件體系,如 Ext4、 XFS、NFS 等等。依照存儲位置的不同,這些文件體系能夠分為三類。
榜首類是依據(jù)磁盤的文件體系,也便是把數(shù)據(jù)直接存儲在計算機本地掛載的磁盤中。常見的 Ext4、XFS、OverlayFS 等,都是這類文件體系。
第二類是依據(jù)內存的文件體系,也便是咱們常說的虛擬文件體系。這類文件體系,不需要任何磁盤分配存儲空間,但會占用內存。咱們經常用到的 /proc 文件體系,其實便是 一種最常見的虛擬文件體系。此外,/sys 文件體系也歸于這一類,首要向用戶空間導出層次化的內核目標。
第三類是網絡文件體系,也便是用來拜訪其他計算機數(shù)據(jù)的文件體系,比方 NFS、 SMB、iSCSI 等。
這些文件體系,要先掛載到 VFS 目錄樹中的某個子目錄(稱為掛載點),然后才干拜訪其間的文件。拿榜首類,也便是依據(jù)磁盤的文件體系為例,在裝置體系時,要先掛載一個根 目錄(/),在根目錄下再把其他文件體系(比方其他的磁盤分區(qū)、/proc 文件體系、/sys 文件體系、NFS 等)掛載進來。
文件體系 I/O
把文件體系掛載到掛載點后,你就能經過掛載點,再去拜訪它辦理的文件了。VFS 供給了一組規(guī)范的文件拜訪接口。這些接口以體系調用的方法,供給給應用程序運用。
就拿 cat 命令來說,它首要調用 open() ,打開一個文件;然后調用 read() ,讀取文件的內容;最終再調用 write() ,把文件內容輸出到控制臺的規(guī)范輸出中:
int open(const char *pathname, int flags, mode_t mode);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
文件讀寫方法的各種差異,導致 I/O 的分類多種多樣。最常見的有,緩沖與非緩沖 I/O、 直接與非直接 I/O、堵塞與非堵塞 I/O、同步與異步 I/O 等。 接下來,咱們就詳細看這四種分類。
榜首種,依據(jù)是否使用規(guī)范庫緩存,能夠把文件 I/O 分為緩沖 I/O 與非緩沖 I/O。
緩沖 I/O,是指使用規(guī)范庫緩存來加快文件的拜訪,而規(guī)范庫內部再經過體系調度拜訪文件。
非緩沖 I/O,是指直接經過體系調用來拜訪文件,不再經過規(guī)范庫緩存。
注意,這里所說的“緩沖”,是目規(guī)范庫內部完結的緩存。比方說,你可能見到過,很多程序遇到換行時才真實輸出,而換行前的內容,其實便是被規(guī)范庫暫時緩存了起來。
無論緩沖 I/O 還對錯緩沖 I/O,它們最終仍是要經過體系調用來拜訪文件。咱們知道,體系調用后,還會經過頁緩存,來削減磁盤的 I/O 操作。
第二,依據(jù)是否使用操作體系的頁緩存,能夠把文件 I/O 分為直接 I/O 與非直接 I/O。
直接 I/O,是指越過操作體系的頁緩存,直接跟文件體系交互來拜訪文件。
非直接 I/O 正好相反,文件讀寫時,先要經過體系的頁緩存,然后再由內核或額外的體系調用,真實寫入磁盤。
想要完結直接 I/O,需要你在體系調用中,指定 O_DIRECT 標志。假如沒有設置過,默許 的對錯直接 I/O。
不過要注意,直接 I/O、非直接 I/O,本質上仍是和文件體系交互。假如是在數(shù)據(jù)庫等場景中,還會看到,越過文件體系讀寫磁盤的狀況,也便是咱們一般所說的裸 I/O。
第三,依據(jù)應用程序是否堵塞本身運轉,能夠把文件 I/O 分為堵塞 I/O 和非堵塞 I/O
所謂堵塞 I/O,是指應用程序履行 I/O 操作后,假如沒有取得呼應,就會堵塞當前線程,天然就不能履行其他任務。
所謂非堵塞 I/O,是指應用程序履行 I/O 操作后,不會堵塞當前的線程,能夠持續(xù)履行其他的任務,隨后再經過輪詢或許事情告知的方法,獲取調用的結果。
比方說,拜訪管道或許網絡套接字時,設置 O_NONBLOCK 標志,就表明用非堵塞方法拜訪;而假如不做任何設置,默許的便是堵塞拜訪。
第四,依據(jù)是否等待呼應結果,能夠把文件 I/O 分為同步和異步 I/O
所謂同步 I/O,是指應用程序履行 I/O 操作后,要一向比及整個 I/O 完結后,才干取得 I/O 呼應。
所謂異步 I/O,是指應用程序履行 I/O 操作后,不必等待完結和完結后的呼應,而是持續(xù)履行就能夠。比及這次 I/O 完結后,呼應會用事情告知的方法,告知應用程序。
例如,在操作文件時,假如設置了 O_SYNC 或許 O_DSYNC 標志,就代表同步 I/O。假如設置了 O_DSYNC,就要等文件數(shù)據(jù)寫入磁盤后,才干返回;而 O_SYNC,則是在 O_DSYNC 基礎上,要求文件元數(shù)據(jù)也要寫入磁盤后,才干返回。
再比方,在拜訪管道或許網絡套接字時,設置了 O_ASYNC 選項后,相應的 I/O 便是異步I/O。這樣,內核會再經過 SIGIO 或許 SIGPOLL,來告知進程文件是否可讀寫。
咱們可能發(fā)現(xiàn)了,這里的很多概念也經常出現(xiàn)在網絡編程中。比方非堵塞 I/O,一般會跟 select/poll 配合,用在網絡套接字的 I/O 中。
這下咱們也應該能夠了解,“Linux 一切皆文件”的深刻含義。無論是普通文件和塊設備、仍是網絡套接字和管道等,它們都經過一致的 VFS 接口來拜訪。