共計(jì) 3269 個(gè)字符,預(yù)計(jì)需要花費(fèi) 9 分鐘才能閱讀完成。
這篇文章主要介紹 linux 硬鏈接和軟鏈接的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
前言
最近前端包管理器 pnpm 真的是太火了,大量的文章分析了 pnpm 的原理。了解之后,發(fā)現(xiàn) pnpm 整個(gè)架構(gòu)都是基于硬鏈接和軟鏈接組織的,但我對(duì)這兩個(gè)概念比較模糊,所以想研究一下。
眾所周知,Unix/Linux 系統(tǒng)中一切皆文件。可見,文件在 Linux 系統(tǒng)中非常重要。我們平常比較直觀的對(duì)于文件的感受肯定是文件名和文件內(nèi)容。但在 Linux 的文件系統(tǒng)中,除了文件名和文件內(nèi)容,還有一個(gè)很重要的概念,就是 inode。
inode
維基百科這樣描述 inode:
The inode (index node) is a data structure in a Unix-style file system that describes a file-system object such as a file or a directory. Each inode stores the attributes and disk block locations of the object s data.File-system object attributes may include metadata (times of last change,access, modification), as well as owner and permission data.
A directory is a list of inodes with their assigned names. The list includes an entry for itself, its parent, and each of its children.
意思就是:inode 是類 Unix 文件系統(tǒng)中用來描述文件系統(tǒng)對(duì)象(比如文件或文件夾)的一種數(shù)據(jù)結(jié)構(gòu)。它存儲(chǔ)著文件的各種屬性(最近一次 inode 變動(dòng)的時(shí)間、最近一次訪問的時(shí)間、最近一次修改的時(shí)間等元信息,以及權(quán)限信息等)。文件夾是一組 inode,包括自身的入口、父節(jié)點(diǎn)的入口以及所有子節(jié)點(diǎn)。
其實(shí),inode 包含的內(nèi)容不止上面這些,具體有:
文件的字節(jié)數(shù)
文件的 User ID
文件的 Group ID
文件的讀、寫、執(zhí)行權(quán)限
時(shí)間戳:ctime,inode 上一次變動(dòng)的時(shí)間;mtime,文件內(nèi)容上一次變動(dòng)的時(shí)間;atime,文件上一次打開的時(shí)間
鏈接數(shù),即有多少個(gè)文件名指向這個(gè) inode
文件數(shù)據(jù) block 的位置
Linux 使用的 ext2/ext3 文件系統(tǒng)中,不同類型的數(shù)據(jù)存放在不同的區(qū)域。inode 組成的 inode table 存放在一個(gè)位置,文件數(shù)據(jù)塊則存在另外一個(gè)位置。
inode 不包含文件名,文件名存放在文件夾信息的結(jié)構(gòu)體里。文件名相當(dāng)于 inode 的別名,便于我們管理和記憶。Linux 系統(tǒng)對(duì)文件的操作都是通過 inode 做到的,當(dāng)我們修改文件時(shí),系統(tǒng)從文件夾的信息結(jié)構(gòu)體里找到文件名對(duì)應(yīng)的 inode,再通過存儲(chǔ)在 inode 中的文件數(shù)據(jù) block 地址找到對(duì)應(yīng)的硬盤位置進(jìn)行讀寫操作。
硬鏈接
一般來說,inode 與文件名、文件數(shù)據(jù)是一對(duì)一的關(guān)系,但我們可以通過 shell 命令讓多個(gè)文件名指向同一個(gè) inode,這種就是硬鏈接(hard link)。
使用 ln origin destination 命令可以創(chuàng)建硬鏈接,如
ln test.txt test_hard.txt
對(duì)應(yīng) nodejs 的 fs.link 方法。
創(chuàng)建硬鏈接前,test.txt 可以這樣表示:
創(chuàng)建硬鏈接后:
可以看到,test_hard.txt 的 inode 跟源文件 test.txt 使用的是同一個(gè),只是現(xiàn)在鏈接數(shù)變成 2 了。
我們可以執(zhí)行 ls -li 查看一下。
第一列是 inode number,可以看到都是 13029546,所以兩個(gè)文件使用的是同一個(gè) inode。第二列是權(quán)限信息,第四列是擁有者,第六列是文件內(nèi)容大小??梢钥吹?,除了文件名不一樣之外,硬鏈接創(chuàng)建的文件跟源文件的所有元信息完全一樣。第三列表示鏈接數(shù),可以看到,目前鏈接數(shù)為 2。
由于硬鏈接文件和源文件使用同一個(gè) inode,并指向同一塊文件數(shù)據(jù),除文件名之外的所有信息都是一樣的。所以這兩個(gè)文件是等價(jià)的,可以說是互為硬鏈接文件。修改任意一個(gè)文件,可以看到另外一個(gè)文件的內(nèi)容也會(huì)同步變化。
軟鏈接
準(zhǔn)確來說叫符號(hào)鏈接(symbolic link),一般又叫軟鏈接(soft link)。與硬鏈接共用一個(gè) inode 不同,軟鏈接會(huì)創(chuàng)建新的 inode,并指向源文件??梢岳斫廛涙溄泳褪?windows 系統(tǒng)中的桌面快捷方式。
創(chuàng)建軟鏈接的命令和硬鏈接很像,多了 - s 參數(shù):ln -s origin destination:
ln -s test.txt test_symbolic.txt
對(duì)應(yīng)的 nodejs 的 fs.symlink 方法。
創(chuàng)建軟鏈接之后:
源文件 inode 的鏈接數(shù)還是 1,創(chuàng)建了新的 inode,軟鏈接指向源文件。
執(zhí)行 ls -li 看一下:
可以看到,軟鏈接的 inode number 跟源文件的不一樣,權(quán)限一列開頭為小寫 L,表示軟鏈,鏈接數(shù)為 1,大小為 8 個(gè)字節(jié)。沒錯(cuò),軟鏈文件也有大小,不過一般很小,畢竟只是一個(gè)快捷方式。
對(duì)比文件重命名或文件移動(dòng)
文件重命名和文件移動(dòng)對(duì)于 Linux 系統(tǒng)來說都是文件絕對(duì)路徑的更改。對(duì)硬鏈接來說,文件重命名或文件移動(dòng)不會(huì)改變鏈接指向,而對(duì)軟鏈接來說,文件重命名或文件移動(dòng)則使鏈接斷開,這時(shí)通過軟鏈接修改文件內(nèi)容時(shí)會(huì)重新創(chuàng)建一個(gè)新的 inode,跟原文件名和文件數(shù)據(jù)塊關(guān)聯(lián)。
文件刪除
rm 命令或者 nodejs 的 unlink 其實(shí)是將 inode 的鏈接數(shù)減 1。對(duì)于前文的硬鏈接,刪除 test_hard.txt 使得 inode1 的鏈接數(shù)變成 1,當(dāng)鏈接數(shù)變成 0 時(shí),系統(tǒng)就會(huì)釋放掉這個(gè) inode,之后再創(chuàng)建的新文件就可以使用該 inode 的 inode number 了。這時(shí)沒有 inode 指向文件數(shù)據(jù) block,所以文件找不到了。但實(shí)際上文件數(shù)據(jù)還存在硬盤中,所以經(jīng)常能看到網(wǎng)上有一些幫助恢復(fù)誤刪的文件的工具。軟鏈接 inode 鏈接數(shù)為 1,刪除軟鏈接則系統(tǒng)釋放該 inode。
鏈接文件和文件夾
軟鏈接可以鏈接文件和文件夾,但硬鏈接只能鏈接文件。
不同文件系統(tǒng)創(chuàng)建鏈接
軟鏈接可以跨不同的文件系統(tǒng)創(chuàng)建,但是硬鏈接不行,因?yàn)橛叉溄邮枪灿靡粋€(gè) inode,而不同的文件系統(tǒng)有不同的 inode table。
應(yīng)用場(chǎng)景硬鏈接
文件備份:為了防止重要的文件被誤刪,文件備份是一種好的辦法,但拷貝文件會(huì)帶來磁盤空間的消耗。硬鏈接能不占用磁盤空間實(shí)現(xiàn)文件備份。
文件共享:多人共同維護(hù)同一份文件時(shí),可以通過硬鏈接的方式,在私人目錄里創(chuàng)建硬鏈接,每個(gè)人的修改都能同步到源文件,但又避免某個(gè)人誤刪就丟掉了文件的問題。
文件分類:不同的文件資源需要分類,比如某個(gè)電影即是的分類是外國、懸疑,那我們可以在外國的文件夾和懸疑的文件夾里分別創(chuàng)建硬鏈接,這樣可以避免重復(fù)拷貝電影浪費(fèi)磁盤空間。有人可能說,使用軟鏈接不也可以嗎?是的,但不太好。因?yàn)橐坏┰次募苿?dòng)位置或者重命名,軟鏈接就失效了。
軟鏈接
快捷方式:對(duì)于路徑很深的文件,查找起來不太方便。利用軟鏈接在桌面創(chuàng)建快捷方式,可以迅速打開并編輯文件。
靈活切換程序版本:對(duì)于機(jī)器上同時(shí)存在多個(gè)版本的程序,可以通過更改軟鏈接的指向,從而迅速切換程序版本。這里提到了 python 版本的切換可以這么做。
動(dòng)態(tài)庫版本管理:不是很懂,具體可以看這里。
總結(jié)
Linux 系統(tǒng)通過 inode 管理文件,inode 存儲(chǔ)著文件字節(jié)數(shù)、文件權(quán)限、鏈接數(shù)、數(shù)據(jù) block 位置等信息。
硬鏈接與源文件共用 inode,除了文件名不同,其他與源文件一樣。不能對(duì)文件夾創(chuàng)建硬鏈接,不能對(duì)不同的文件系統(tǒng)的文件創(chuàng)建硬鏈接。
軟鏈接類似于 windows 的快捷方式,有獨(dú)立的 inode??梢詫?duì)文件夾或不同文件系統(tǒng)的文件創(chuàng)建軟鏈接。
硬鏈接和軟鏈接修改文件內(nèi)容都會(huì)同步到源文件,因?yàn)楸举|(zhì)上它們都是指向源文件的數(shù)據(jù) block。
以上是“l(fā)inux 硬鏈接和軟鏈接的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道!