日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
從根上理解 Node.js 的 Fs 模塊:一起設(shè)計(jì)一個(gè)文件系統(tǒng)

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

創(chuàng)新互聯(lián)建站是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專(zhuān)注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開(kāi)發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號(hào)開(kāi)發(fā),軟件開(kāi)發(fā),微信小程序開(kāi)發(fā),十年建站對(duì)成都砂巖浮雕等多個(gè)行業(yè),擁有豐富的網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn)。

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

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

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

什么是文件呢?

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

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

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

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

簡(jiǎn)單想了下:挨著放。

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

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

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

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

怎么辦呢?如何更好的利用磁盤(pán)空間?

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

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

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

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

妙啊!

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

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

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

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

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

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

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

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

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

簡(jiǎn)單理一下我們?cè)O(shè)計(jì)的文件系統(tǒng):

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

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

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

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

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

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

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

現(xiàn)在把我們?cè)O(shè)計(jì)好的文件系統(tǒng)交給用戶(hù),就可以通過(guò)它來(lái)高效利用硬盤(pán)了。

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

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

查詢(xún)起來(lái)慢,也容易命名沖突。

怎么辦呢?

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

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

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

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

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

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

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

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

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

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

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

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

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

現(xiàn)在一個(gè) inode 只有一條路徑過(guò)來(lái),因?yàn)槭菢?shù)嘛,那如果我想兩條路徑都可以找到同一個(gè) inode 呢?

比如 /A/D/dongdong.jpg 可以訪問(wèn)到該文件:

我想通過(guò) /A/B/dongdong.jpg 也能訪問(wèn),怎么辦呢?

直接指過(guò)去不就行了。

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

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

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

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

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

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

為什么叫硬呢?因?yàn)楦牟涣?,直接指向同一個(gè) inode。

為什么叫軟呢?因?yàn)榭梢愿?,多了一?inode 用來(lái)改名。

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

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

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

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

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

復(fù)盤(pán)一下我們?cè)O(shè)計(jì)的文件系統(tǒng):

v1.0:

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

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

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

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

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

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

v2.0:

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

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

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

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

v3.0:

通過(guò)多個(gè)目錄 inode 包含同一個(gè) inode 的方式,來(lái)實(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)也是類(lèi)似的實(shí)現(xiàn),目前有很多文件系統(tǒng),比如 ext2、FAT 等,原理和我們?cè)O(shè)計(jì)的文件系統(tǒng)差不多。

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

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

Node.js 通過(guò) V8 注入了 fs 的 api 給 js 用,底層是通過(guò) 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)之后,我們?cè)賮?lái)看下 fs 的 api,是不是理解更深了:

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

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

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

總結(jié)

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

  • 把文件分成不同數(shù)據(jù)塊,這樣可以高效利用磁盤(pán)空間。
  • 文件的索引節(jié)點(diǎn) index node 中記錄了所包含的數(shù)據(jù)塊和創(chuàng)建時(shí)間、權(quán)限、是否是目錄等信息。
  • 通過(guò)塊位圖記錄數(shù)據(jù)塊空閑狀態(tài)。
  • 通過(guò) inode 位圖記錄 inode 空閑狀態(tài)。
  • 通過(guò)超級(jí)塊記錄硬盤(pán)的 inode、數(shù)據(jù)塊的使用信息。
  • 通過(guò) inode 對(duì)應(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 用于改名,對(duì)應(yīng)數(shù)據(jù)塊中指向目標(biāo) inode。

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


文章標(biāo)題:從根上理解 Node.js 的 Fs 模塊:一起設(shè)計(jì)一個(gè)文件系統(tǒng)
文章分享:http://www.5511xx.com/article/dhejsdo.html