成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從根上理解 Node.js 的 Fs 模塊:一起設(shè)計(jì)一個(gè)文件系統(tǒng)

開發(fā) 前端
Node.js 提供了 File System 的 api,可以讀寫文件、目錄、修改權(quán)限、創(chuàng)建軟鏈等。可能大家 api 用的比較熟練,但對于這些 api 的原理不一定理解。要想真正理解 File System,還得從根上來看。

[[424137]]

Node.js 提供了 File System 的 api,可以讀寫文件、目錄、修改權(quán)限、創(chuàng)建軟鏈等。

可能大家 api 用的比較熟練,但對于這些 api 的原理不一定理解。要想真正理解 File System,還得從根上來看。

下面我們從 0 到 1 設(shè)計(jì)一個(gè)文件系統(tǒng)試試。

從 0 到 1 設(shè)計(jì)一個(gè)文件系統(tǒng)

什么是文件呢?

[[424138]]

這樣一份比較完整的資料就是文件。

但是計(jì)算機(jī)的持久化存儲是在硬盤,主要是磁盤和 SSD 固定硬盤:

計(jì)算機(jī)里的文件是一個(gè)邏輯概念,并不是物理上存在的一個(gè)個(gè)實(shí)體。

那么如果給了這樣一個(gè)硬盤,讓我們自己造一個(gè)文件系統(tǒng)出來,實(shí)現(xiàn)文件的功能。怎么做呢?

簡單想了下:挨著放。

然后還要記錄下索引,啥文件在啥位置:

這樣是可以,但是有個(gè)問題,萬一文件 B 被刪除了,那對應(yīng)的空間就要釋放:

然后又來了一個(gè)文件 D,發(fā)現(xiàn)放不進(jìn)去啊,這地方太小了。

A 和 B 中間這塊空間就是碎片,碎片會把磁盤可用空間割裂成不連續(xù)的很多小塊。

怎么辦呢?如何更好的利用磁盤空間?

分塊!把文件分成一小塊一小塊的,比如 1k 為一個(gè)塊,可以不用連續(xù)存,把所有塊記錄在索引中就行了。

索引咋記錄的看不清,放大點(diǎn)來看:

每個(gè)文件的索引中都記錄了把數(shù)據(jù)存在了哪幾個(gè)塊,這樣一塊一塊的讀出來就行了。

而且文件刪除了,那些塊還可以繼續(xù)用,不會有很大的碎片。

妙啊!

難怪文件系統(tǒng)第一步就是分塊,內(nèi)存管理第一步是分頁,這樣才能高效利用空間啊。

這種索引節(jié)點(diǎn),可以叫做 index node,簡稱 inode 就好了。

而且,除了文件名和存放的塊以外,還可以記錄其他信息,比如創(chuàng)建時(shí)間、修改時(shí)間、文件權(quán)限、所屬用戶等等。

到這里就可以對文件下個(gè)物理層面上的定義了: 文件就是 inode 記錄的信息和它所索引的一系列數(shù)據(jù)塊。

那我寫文件利用了一個(gè)塊,刪除文件釋放了一個(gè)塊,怎么知道呢?得單獨(dú)記錄下來塊的狀態(tài)。

數(shù)據(jù)塊只有空閑和被占用兩個(gè)狀態(tài),一個(gè)二進(jìn)制位就行了。通過一段二進(jìn)制數(shù)把所有塊的空閑狀態(tài)記錄下來。一個(gè)位代表一個(gè)值,這叫做位圖。在這里就是塊位圖。

硬盤中大部分是數(shù)據(jù)塊,開頭的一段來放 inode 所在的塊和數(shù)據(jù)塊的塊位圖。

inode 也是存在塊里的,比如我們規(guī)定只能用 5 個(gè)塊放 inode,那 inode 總量是有限的,也就是是說文件系統(tǒng)可以創(chuàng)建的文件是有上限的。

我們也要記錄下所有 inode 的空閑狀態(tài),也就是 inode 位圖。

簡單理一下我們設(shè)計(jì)的文件系統(tǒng):

為了更好的利用硬盤空間,我們對數(shù)據(jù)進(jìn)行了分塊,每個(gè)文件用到了哪些塊記錄在 inode 里。inode 還記錄了文件的創(chuàng)建時(shí)間、修改時(shí)間、權(quán)限等信息。

通過塊位圖來記錄數(shù)據(jù)塊空閑狀態(tài),通過 inode 位圖來記錄 inode 的空閑狀態(tài)。

但我如果想知道硬盤中有幾個(gè)塊、用了幾個(gè),有幾個(gè) inode、用了幾個(gè),怎么辦呢?

簡單,遍歷一遍塊位圖和 inode 位圖,就知道個(gè)數(shù)了。

但每次這么算太慢了,這就像我們設(shè)計(jì)數(shù)據(jù)庫的時(shí)候,一個(gè)論壇下面有多少個(gè)帖子,這個(gè)數(shù)據(jù)不會是每次用 sql 查詢的,而是在帖子增刪的時(shí)候動態(tài)維護(hù)一個(gè)字段在數(shù)據(jù)庫表中,直接查詢即可。

那我們也設(shè)計(jì)一個(gè)塊用來存這種統(tǒng)計(jì)信息,也就是:

這個(gè)塊是較高層的統(tǒng)計(jì)信息,我們可以叫它超級塊。

現(xiàn)在把我們設(shè)計(jì)好的文件系統(tǒng)交給用戶,就可以通過它來高效利用硬盤了。

發(fā)布版本:神光文件系統(tǒng) V1.0。

但現(xiàn)在我們的文件系統(tǒng)好像還不是很好用,只能創(chuàng)建文件,那如果我創(chuàng)建了 1000 個(gè)文件呢?

查詢起來慢,也容易命名沖突。

怎么辦呢?

命名空間!目錄!就像文件夾的思想一樣。

那怎么實(shí)現(xiàn)呢?

每個(gè) inode 是一個(gè)文件,那把 inode 組織成樹不就行了。

比如我們有兩個(gè)文件 B 和 C:

我們創(chuàng)建一個(gè)目錄 A:

在 inode 里面添加一個(gè) isDirectory 的屬性,如果是目錄,那么就讀取數(shù)據(jù)塊的內(nèi)容,找到其中的 inode 節(jié)點(diǎn)編號,就知道該目錄下的文件了。

這就是目錄的實(shí)現(xiàn)原理:通過 inode 的 isDirectory 屬性區(qū)分是文件還是目錄,如果是目錄就讀取數(shù)據(jù)塊中的 inode 信息來查找子文件,如果是文件,則直接讀取數(shù)據(jù)塊作為文件內(nèi)容。

從一個(gè) inode 到另一個(gè) inode 的查找順序叫做路徑(path)。

比如這樣一個(gè)文件的 inode 查找順序:

那文件路徑就是 /A/D/dongdong.jpg

這就是文件路徑的本質(zhì):文件路徑就是 inode 查找順序

現(xiàn)在我們支持目錄的嵌套了,可以把文件、目錄組織成樹形結(jié)構(gòu)方便管理。

發(fā)布版本:神光文件系統(tǒng) v2.0。

現(xiàn)在一個(gè) inode 只有一條路徑過來,因?yàn)槭菢渎铮侨绻蚁雰蓷l路徑都可以找到同一個(gè) inode 呢?

比如 /A/D/dongdong.jpg 可以訪問到該文件:

我想通過 /A/B/dongdong.jpg 也能訪問,怎么辦呢?

直接指過去不就行了。

這樣確實(shí)可以有兩條路徑找到同一個(gè)文件,這個(gè)額外的鏈接我們起名叫做硬鏈接。

但是因?yàn)橐粋€(gè)節(jié)點(diǎn)有兩個(gè)父節(jié)點(diǎn),就不再是樹了,變成了圖。所以,文件樹這個(gè)概念嚴(yán)格意義上來說還是存在問題的,可能是個(gè)文件圖。

但是我如果想給 dongdong.jpg 換個(gè)名字,叫 dongdong2.jpg 呢?

現(xiàn)在都是同一個(gè) inode 節(jié)點(diǎn),改了就都改了。但我只想改 /A/B 的 path 的文件名,別的不改。

那就再創(chuàng)建個(gè) inode 節(jié)點(diǎn),用來改名,然后這個(gè) inode 節(jié)點(diǎn)指向 dongdong.jpg。

這種不直接指過去,多了一個(gè) inode 來改名,之后再指過去,這種我們叫做軟鏈接。

為什么叫硬呢?因?yàn)楦牟涣耍苯又赶蛲粋€(gè) inode。

為什么叫軟呢?因?yàn)榭梢愿模嗔艘粚?inode 用來改名。

所以我們分別起名硬軟鏈接。

硬鏈接和軟鏈接都是用于多條路徑可以查找到同一個(gè)文件的,但是硬鏈接不能單獨(dú)改名,軟連接可以。

monorepo 的實(shí)現(xiàn)就是基于軟連接的,可以指向同一個(gè)目錄 inode,而且還可以起個(gè)別名。

實(shí)現(xiàn)了軟硬鏈接,可以發(fā)新版本了。

發(fā)布版本:神光文件系統(tǒng) v3.0。

復(fù)盤一下我們設(shè)計(jì)的文件系統(tǒng):

v1.0:

通過數(shù)據(jù)塊來存儲文件內(nèi)容,提高硬盤利用效率

通過 inode 記錄所用的數(shù)據(jù)塊和文件的創(chuàng)建時(shí)間、權(quán)限等信息

通過塊位圖記錄數(shù)據(jù)塊的空閑狀態(tài)

通過 inode 位圖記錄 inode 空閑狀態(tài)。

通過超級塊記錄 inode 和數(shù)據(jù)塊的統(tǒng)計(jì)信息。

這個(gè)版本實(shí)現(xiàn)了文件的存取,但是不支持目錄。

v2.0:

通過 inode 中添加一個(gè)屬性來記錄是文件還是目錄

目錄的數(shù)據(jù)塊中存放具體文件列表的 inode 信息,讀取目錄的時(shí)候可以讀取出文件列表。

按照目錄 inode、文件 inode 的一層層的查找順序叫做文件路徑。

這個(gè)版本實(shí)現(xiàn)了目錄和路徑的功能。

v3.0:

通過多個(gè)目錄 inode 包含同一個(gè) inode 的方式,來實(shí)現(xiàn)多條路徑查找同一文件的功能,叫做硬鏈接。

目錄先創(chuàng)建一個(gè) inode 節(jié)點(diǎn)用于改名,然后該 inode 節(jié)點(diǎn)指向目標(biāo) inode 節(jié)點(diǎn),這叫做軟連接。

這個(gè)版本實(shí)現(xiàn)了多條路徑查找統(tǒng)一文件的軟硬鏈接功能。

真實(shí)的文件系統(tǒng)也是類似的實(shí)現(xiàn),目前有很多文件系統(tǒng),比如 ext2、FAT 等,原理和我們設(shè)計(jì)的文件系統(tǒng)差不多。

文件系統(tǒng)設(shè)計(jì)完了,回到最開始的目標(biāo),我們是想深入理解 Node.js 的 File System 的 api。下面就來看一下。

Node.js 的文件系統(tǒng) api

Node.js 通過 V8 注入了 fs 的 api 給 js 用,底層是通過 c++ 調(diào)用操作系統(tǒng)的文件系統(tǒng)功能,也就是我們上面設(shè)計(jì)的那種文件系統(tǒng)。

我們調(diào)用的 fs 的 api 最終就是調(diào)用了操作系統(tǒng)的文件系統(tǒng)功能。

自己設(shè)計(jì)了一個(gè)文件系統(tǒng)之后,我們再來看下 fs 的 api,是不是理解更深了:

  • fs.stat 獲取 inode 中的信息的
  • fs.chmod 修改文件權(quán)限,也是修改 inode 信息
  • fs.chown 修改所屬用戶,也是修改 inode 信息
  • fs.copyFile 復(fù)制 inode 和數(shù)據(jù)塊,把新的 inode 添加到對應(yīng)目錄的 inode 內(nèi)容中
  • fs.link 創(chuàng)建軟硬鏈接的,也就是多條路徑查找同一個(gè)文件的 inode,軟連接還可以改名
  • fs.mkdir 創(chuàng)建目錄 inode 的
  • fs.rmdir 讀取目錄 inode 包含的所有文件 inode 的

具體 api 還有很多,但都是用來操作我們上面設(shè)計(jì)的那個(gè)文件系統(tǒng)的。

從根上理解了文件系統(tǒng),用這些 api 也會得心應(yīng)手。

總結(jié)

為了真正理解 Node.js 的 fs 模塊,我們一起設(shè)計(jì)了一個(gè)文件系統(tǒng):

  • 把文件分成不同數(shù)據(jù)塊,這樣可以高效利用磁盤空間。
  • 文件的索引節(jié)點(diǎn) index node 中記錄了所包含的數(shù)據(jù)塊和創(chuàng)建時(shí)間、權(quán)限、是否是目錄等信息。
  • 通過塊位圖記錄數(shù)據(jù)塊空閑狀態(tài)。
  • 通過 inode 位圖記錄 inode 空閑狀態(tài)。
  • 通過超級塊記錄硬盤的 inode、數(shù)據(jù)塊的使用信息。
  • 通過 inode 對應(yīng)的數(shù)據(jù)塊內(nèi)容包含文件 inode 信息列表的方式實(shí)現(xiàn)了目錄節(jié)點(diǎn)。

我們得出一些重要結(jié)論:

文件本質(zhì)上就是 inode + 數(shù)據(jù)塊。

路徑本質(zhì)上就是查找目標(biāo) inode 的路徑。

硬鏈接本質(zhì)上就是多個(gè)目錄 inode 包含同一個(gè) inode。

軟連接本質(zhì)上就是多創(chuàng)建了一個(gè) inode 用于改名,對應(yīng)數(shù)據(jù)塊中指向目標(biāo) inode。

Node.js 的 fs api 是通過 c++ 注入 v8 的對操作系統(tǒng)能力的調(diào)用,理解了文件系統(tǒng),再學(xué)那些 api 就很輕松了。

 

責(zé)任編輯:武曉燕 來源: 神光的編程秘籍
相關(guān)推薦

2022-04-07 09:29:04

文件系統(tǒng)硬盤操作系統(tǒng)

2021-10-12 23:45:43

NodeJs事件

2023-06-20 06:44:14

Node.jsCPU 負(fù)載

2020-11-05 09:27:48

JavaScript開發(fā)技術(shù)

2024-06-17 11:59:39

2011-10-25 09:28:30

Node.js

2013-11-01 09:34:56

Node.js技術(shù)

2020-08-07 10:40:56

Node.jsexpress前端

2022-10-18 18:43:40

Node.js低代碼

2024-03-26 10:38:47

模塊CommonJSES

2019-12-17 11:40:44

Node.js模塊前端

2020-08-24 08:07:32

Node.js文件函數(shù)

2024-03-11 10:30:31

Linux文件系統(tǒng)

2024-02-28 08:47:29

文件系統(tǒng)數(shù)據(jù)

2022-08-29 07:48:27

文件數(shù)據(jù)參數(shù)類型

2011-06-17 10:29:04

Nodejavascript

2022-06-05 13:52:32

Node.jsDNS 的原理DNS 服務(wù)器

2024-09-10 08:06:41

2021-09-26 05:06:04

Node.js模塊機(jī)制

2023-04-11 07:48:32

WebGLCanvas
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美精品二区 | 久久精品99国产精品 | 狠狠伊人 | 夜色www国产精品资源站 | av网站免费观看 | 国产精品久久久久久久久免费樱桃 | 中文字幕不卡在线88 | 一区二区在线观看免费视频 | 久久狠狠| 国产美女精品 | 精品久久久久久久久久久院品网 | 欧美成人一区二区三区片免费 | 在线观看a视频 | 国产农村妇女毛片精品久久麻豆 | 欧美精品一区二区在线观看 | 不卡一区 | 免费视频一区 | 亚洲在线视频 | 亚洲一区二区三区高清 | a看片| 精品伊人久久 | 国产欧美精品 | 国产免费拔擦拔擦8x高清 | 一区二区福利视频 | 欧美一区日韩一区 | 成人精品国产免费网站 | 日韩资源| 午夜精品 | 国产中文 | 国产精品久久久久久 | 成人午夜影院 | 日本不卡免费新一二三区 | 欧美三级在线 | 青青草一区 | 国产无套一区二区三区久久 | 国产在线网站 | caoporn国产精品免费公开 | 欧美国产激情二区三区 | 国产精品久久久久aaaa樱花 | 欧美一区二区三区大片 | 中文字幕 在线观看 |