Linux文件系統(tǒng)基本概念是什么

這篇文章主要講解了“Linux文件系統(tǒng)基本概念是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Linux文件系統(tǒng)基本概念是什么”吧!

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:主機域名虛擬主機、營銷軟件、網(wǎng)站建設(shè)、安丘網(wǎng)站維護、網(wǎng)站推廣。

Linux 文件系統(tǒng)基本概念

Linux 在最初的設(shè)計是 MINIX1 文件系統(tǒng),它只支持 14 字節(jié)的文件名,它的最大文件只支持到 64 MB。在  MINIX 1 之后的文件系統(tǒng)是 ext 文件系統(tǒng)。ext 系統(tǒng)相較于 MINIX 1 來說,在支持字節(jié)大小和文件大小上均有很大提升,但是 ext 的速度仍沒有  MINIX 1 快,于是,ext 2 被開發(fā)出來,它能夠支持長文件名和大文件,而且具有比 MINIX 1 更好的性能。這使他成為 Linux  的主要文件系統(tǒng)。只不過 Linux 會使用 VFS 曾支持多種文件系統(tǒng)。在 Linux 鏈接時,用戶可以動態(tài)的將不同的文件系統(tǒng)掛載倒 VFS 上。

Linux 中的文件是一個任意長度的字節(jié)序列,Linux 中的文件可以包含任意信息,比如 ASCII 碼、二進制文件和其他類型的文件是不加區(qū)分的。

為了方便起見,文件可以被組織在一個目錄中,目錄存儲成文件的形式在很大程度上可以作為文件處理。目錄可以有子目錄,這樣形成有層次的文件系統(tǒng),Linux  系統(tǒng)下面的根目錄是 / ,它通常包含了多個子目錄。字符 / 還用于對目錄名進行區(qū)分,例如 「/usr/cxuan」 表示的就是根目錄下面的 usr  目錄,其中有一個叫做 cxuan 的子目錄。

下面我們介紹一下 Linux 系統(tǒng)根目錄下面的目錄名

  • /bin,它是重要的二進制應(yīng)用程序,包含二進制文件,系統(tǒng)的所有用戶使用的命令都在這里

  • /boot,啟動包含引導(dǎo)加載程序的相關(guān)文件

  • /dev,包含設(shè)備文件,終端文件,USB 或者連接到系統(tǒng)的任何設(shè)備

  • /etc,配置文件,啟動腳本等,包含所有程序所需要的配置文件,也包含了啟動/停止單個應(yīng)用程序的啟動和關(guān)閉 shell 腳本

  • /home,本地主要路徑,所有用戶用 home 目錄存儲個人信息

  • /lib,系統(tǒng)庫文件,包含支持位于 /bin 和 /sbin 下的二進制庫文件

  • /lost+found,在根目錄下提供一個遺失+查找系統(tǒng),必須在 root 用戶下才能查看當(dāng)前目錄下的內(nèi)容

  • /media,掛載可移動介質(zhì)

  • /mnt,掛載文件系統(tǒng)

  • /opt,提供一個可選的應(yīng)用程序安裝目錄

  • /proc,特殊的動態(tài)目錄,用于維護系統(tǒng)信息和狀態(tài),包括當(dāng)前運行中進程信息

  • /root,root 用戶的主要目錄文件夾

  • /sbin,重要的二進制系統(tǒng)文件

  • /tmp, 系統(tǒng)和用戶創(chuàng)建的臨時文件,系統(tǒng)重啟時,這個目錄下的文件都會被刪除

  • /usr,包含絕大多數(shù)用戶都能訪問的應(yīng)用程序和文件

  • /var,經(jīng)常變化的文件,諸如日志文件或數(shù)據(jù)庫等

在 Linux 中,有兩種路徑,一種是 絕對路徑(absolute path)  ,絕對路徑告訴你從根目錄下查找文件,絕對路徑的缺點是太長而且不太方便。還有一種是 相對路徑(relative path)  ,相對路徑所在的目錄也叫做工作目錄(working directory)。

如果 /usr/local/books 是工作目錄,那么 shell 命令

cp books books-replica

就表示的是相對路徑,而

cp /usr/local/books/books /usr/local/books/books-replica

則表示的是絕對路徑。

在 Linux  中經(jīng)常出現(xiàn)一個用戶使用另一個用戶的文件或者使用文件樹結(jié)構(gòu)中的文件。兩個用戶共享同一個文件,這個文件位于某個用戶的目錄結(jié)構(gòu)中,另一個用戶需要使用這個文件時,必須通過絕對路徑才能引用到他。如果絕對路徑很長,那么每次輸入起來會變的非常麻煩,所以  Linux 提供了一種 鏈接(link) 機制。

舉個例子,下面是一個使用鏈接之前的圖

Linux文件系統(tǒng)基本概念是什么

以上所示,比如有兩個工作賬戶 jianshe 和 cxuan,jianshe 想要使用 cxuan 賬戶下的 A 目錄,那么它可能會輸入  /usr/cxuan/A ,這是一種未使用鏈接之后的圖。

使用鏈接后的示意如下

Linux文件系統(tǒng)基本概念是什么

現(xiàn)在,jianshe 可以創(chuàng)建一個鏈接來使用 cxuan 下面的目錄了。‘

當(dāng)一個目錄被創(chuàng)建出來后,有兩個目錄項也同時被創(chuàng)建出來,它們就是 . 和 ..  ,前者代表工作目錄自身,后者代表該目錄的父目錄,也就是該目錄所在的目錄。這樣一來,在 /usr/jianshe 中訪問 cxuan 中的目錄就是  ../cxuan/xxxLinux  文件系統(tǒng)不區(qū)分磁盤的,這是什么意思呢?一般來說,一個磁盤中的文件系統(tǒng)相互之間保持獨立,如果一個文件系統(tǒng)目錄想要訪問另一個磁盤中的文件系統(tǒng),在 Windows  中你可以像下面這樣。

Linux文件系統(tǒng)基本概念是什么

兩個文件系統(tǒng)分別在不同的磁盤中,彼此保持獨立。

而在 Linux 中,是支持掛載的,它允許一個磁盤掛在到另外一個磁盤上,那么上面的關(guān)系會變成下面這樣

Linux文件系統(tǒng)基本概念是什么

掛在之后,兩個文件系統(tǒng)就不再需要關(guān)心文件系統(tǒng)在哪個磁盤上了,兩個文件系統(tǒng)彼此可見。

Linux 文件系統(tǒng)的另外一個特性是支持  加鎖(locking)。在一些應(yīng)用中會出現(xiàn)兩個或者更多的進程同時使用同一個文件的情況,這樣很可能會導(dǎo)致競爭條件(race  condition)。一種解決方法是對其進行加不同粒度的鎖,就是為了防止某一個進程只修改某一行記錄從而導(dǎo)致整個文件都不能使用的情況。

POSIX  提供了一種靈活的、不同粒度級別的鎖機制,允許一個進程使用一個不可分割的操作對一個字節(jié)或者整個文件進行加鎖。加鎖機制要求嘗試加鎖的進程指定其「要加鎖的文件,開始位置以及要加鎖的字節(jié)」

Linux  系統(tǒng)提供了兩種鎖:「共享鎖和互斥鎖」。如果文件的一部分已經(jīng)加上了共享鎖,那么再加排他鎖是不會成功的;如果文件系統(tǒng)的一部分已經(jīng)被加了互斥鎖,那么在互斥鎖解除之前的任何加鎖都不會成功。為了成功加鎖、請求加鎖的部分的所有字節(jié)都必須是可用的。

在加鎖階段,進程需要設(shè)計好加鎖失敗后的情況,也就是判斷加鎖失敗后是否選擇阻塞,如果選擇阻塞式,那么當(dāng)已經(jīng)加鎖的進程中的鎖被刪除時,這個進程會解除阻塞并替換鎖。如果進程選擇非阻塞式的,那么就不會替換這個鎖,會立刻從系統(tǒng)調(diào)用中返回,標(biāo)記狀態(tài)碼表示是否加鎖成功,然后進程會選擇下一個時間再次嘗試。

加鎖區(qū)域是可以重疊的。下面我們演示了三種不同條件的加鎖區(qū)域。

Linux文件系統(tǒng)基本概念是什么

如上圖所示,A 的共享鎖在第四字節(jié)到第八字節(jié)進行加鎖

Linux文件系統(tǒng)基本概念是什么

如上圖所示,進程在 A 和 B 上同時加了共享鎖,其中 6 - 8 字節(jié)是重疊鎖

Linux文件系統(tǒng)基本概念是什么

如上圖所示,進程 A 和 B 和 C 同時加了共享鎖,那么第六字節(jié)和第七字節(jié)是共享鎖。

如果此時一個進程嘗試在第 6 個字節(jié)處加鎖,此時會設(shè)置失敗并阻塞,由于該區(qū)域被 A B C 同時加鎖,那么只有等到 A B C  都釋放鎖后,進程才能加鎖成功。

Linux 文件系統(tǒng)調(diào)用

許多系統(tǒng)調(diào)用都會和文件與文件系統(tǒng)有關(guān)。我們首先先看一下對單個文件的系統(tǒng)調(diào)用,然后再來看一下對整個目錄和文件的系統(tǒng)調(diào)用。

為了創(chuàng)建一個新的文件,會使用到 creat 方法,注意沒有 e。

?這里說一個小插曲,曾經(jīng)有人問 UNIX 創(chuàng)始人 Ken Thompson,如果有機會重新寫 UNIX ,你會怎么辦,他回答自己要把 creat 改成  create ,哈哈哈哈。?

這個系統(tǒng)調(diào)用的兩個參數(shù)是文件名和保護模式

fd = creat("aaa",mode);

這段命令會創(chuàng)建一個名為 aaa 的文件,并根據(jù) mode 設(shè)置文件的保護位。這些位決定了哪個用戶可能訪問文件、如何訪問。

creat 系統(tǒng)調(diào)用不僅僅創(chuàng)建了一個名為 aaa 的文件,還會打開這個文件。為了允許后續(xù)的系統(tǒng)調(diào)用訪問這個文件,這個 creat 系統(tǒng)調(diào)用會返回一個  非負(fù)整數(shù), 這個就叫做 文件描述符(file descriptor),也就是上面的 fd。

如果在已經(jīng)存在的文件上調(diào)用了 creat 系統(tǒng)調(diào)用,那么該文件中的內(nèi)容會被清除,從 0 開始。通過設(shè)置合適的參數(shù),open  系統(tǒng)調(diào)用也能夠創(chuàng)建文件。

下面讓我們看一看主要的系統(tǒng)調(diào)用,如下表所示

系統(tǒng)調(diào)用描述
fd = creat(name,mode)一種創(chuàng)建一個新文件的方式
fd = open(file, ...)打開文件讀、寫或者讀寫
s = close(fd)關(guān)閉一個打開的文件
n = read(fd, buffer, nbytes)從文件中向緩存中讀入數(shù)據(jù)
n = write(fd, buffer, nbytes)從緩存中向文件中寫入數(shù)據(jù)
position = lseek(fd, offset, whence)移動文件指針
s = stat(name, &buf)獲取文件信息
s = fstat(fd, &buf)獲取文件信息
s = pipe(&fd[0])創(chuàng)建一個管道
s = fcntl(fd,...)文件加鎖等其他操作

為了對一個文件進行讀寫的前提是先需要打開文件,必須使用 creat 或者 open 打開,參數(shù)是打開文件的方式,是只讀、可讀寫還是只寫。open  系統(tǒng)調(diào)用也會返回文件描述符。打開文件后,需要使用 close 系統(tǒng)調(diào)用進行關(guān)閉。close 和 open 返回的 fd 總是未被使用的最小數(shù)量。

?什么是文件描述符?文件描述符就是一個數(shù)字,這個數(shù)字標(biāo)示了計算機操作系統(tǒng)中打開的文件。它描述了數(shù)據(jù)資源,以及訪問資源的方式。?

  • 當(dāng)程序要求打開一個文件時,內(nèi)核會進行如下操作

  • 授予訪問權(quán)限

  • 在全局文件表(global file table)中創(chuàng)建一個條目(entry)向軟件提供條目的位置

文件描述符由唯一的非負(fù)整數(shù)組成,系統(tǒng)上每個打開的文件至少存在一個文件描述符。文件描述符最初在 Unix 中使用,并且被包括 Linux,macOS 和  BSD 在內(nèi)的現(xiàn)代操作系統(tǒng)所使用。

當(dāng)一個進程成功訪問一個打開的文件時,內(nèi)核會返回一個文件描述符,這個文件描述符指向全局文件表的 entry 項。這個文件表項包含文件的 inode  信息,字節(jié)位移,訪問限制等。例如下圖所示

Linux文件系統(tǒng)基本概念是什么

默認(rèn)情況下,前三個文件描述符為 STDIN(標(biāo)準(zhǔn)輸入)、STDOUT(標(biāo)準(zhǔn)輸出)、STDERR(標(biāo)準(zhǔn)錯誤)。

標(biāo)準(zhǔn)輸入的文件描述符是 0 ,在終端中,默認(rèn)為用戶的鍵盤輸入

標(biāo)準(zhǔn)輸出的文件描述符是 1 ,在終端中,默認(rèn)為用戶的屏幕

與錯誤有關(guān)的默認(rèn)數(shù)據(jù)流是 2,在終端中,默認(rèn)為用戶的屏幕。

在簡單聊了一下文件描述符后,我們繼續(xù)回到文件系統(tǒng)調(diào)用的探討。

在文件系統(tǒng)調(diào)用中,開銷最大的就是 read 和 write 了。read 和 write 都有三個參數(shù)

  • 文件描述符:告訴需要對哪一個打開文件進行讀取和寫入

  • 緩沖區(qū)地址:告訴數(shù)據(jù)需要從哪里讀取和寫入哪里

  • 統(tǒng)計:告訴需要傳輸多少字節(jié)

這就是所有的參數(shù)了,這個設(shè)計非常簡單輕巧。

雖然幾乎所有程序都按順序讀取和寫入文件,但是某些程序需要能夠隨機訪問文件的任何部分。與每個文件相關(guān)聯(lián)的是一個指針,該指針指示文件中的當(dāng)前位置。順序讀取(或?qū)懭?時,它通常指向要讀取(寫入)的下一個字節(jié)。如果指針在讀取  1024 個字節(jié)之前位于 4096 的位置,則它將在成功讀取系統(tǒng)調(diào)用后自動移至 5120 的位置。

Lseek 系統(tǒng)調(diào)用會更改指針位置的值,以便后續(xù)對 read 或 write 的調(diào)用可以在文件中的任何位置開始,甚至可以超出文件末尾。

?lseek = Lseek ,段首大寫。?

lseek 避免叫做 seek 的原因就是 seek 已經(jīng)在之前 16 位的計算機上用于搜素功能了。

Lseek 有三個參數(shù):第一個是文件的文件描述符,第二個是文件的位置;第三個告訴文件位置是相對于文件的開頭,當(dāng)前位置還是文件的結(jié)尾

lseek(int fildes, off_t offset, int whence);

lseek 的返回值是更改文件指針后文件中的絕對位置。lseek  是唯一從來不會造成真正磁盤查找的系統(tǒng)調(diào)用,它只是更新當(dāng)前的文件位置,這個文件位置就是內(nèi)存中的數(shù)字。

對于每個文件,Linux 都會跟蹤文件模式(常規(guī),目錄,特殊文件),大小,最后修改時間以及其他信息。程序能夠通過 stat  系統(tǒng)調(diào)用看到這些信息。第一個參數(shù)就是文件名,第二個是指向要放置請求信息結(jié)構(gòu)的指針。這些結(jié)構(gòu)的屬性如下圖所示。

存儲文件的設(shè)備
存儲文件的設(shè)備
i-node 編號
文件模式(包括保護位信息)
文件鏈接的數(shù)量
文件所有者標(biāo)識
文件所屬的組
文件大小(字節(jié))
創(chuàng)建時間
最后一個修改/訪問時間

fstat 調(diào)用和 stat 相同,只有一點區(qū)別,fstat 可以對打開文件進行操作,而 stat 只能對路徑進行操作。

pipe 文件系統(tǒng)調(diào)用被用來創(chuàng)建 shell  管道。它會創(chuàng)建一系列的偽文件,來緩沖和管道組件之間的數(shù)據(jù),并且返回讀取或者寫入緩沖區(qū)的文件描述符。在管道中,像是如下操作

sort <in | head &ndash;40

sort 進程將會輸出到文件描述符1,也就是標(biāo)準(zhǔn)輸出,寫入管道中,而 head 進程將從管道中讀入。在這種方式中,sort 只是從文件描述符 0  中讀取并寫入到文件描述符 1 (管道)中,甚至不知道它們已經(jīng)被重定向了。如果沒有重定向的話,sort 會自動的從鍵盤讀入并輸出到屏幕中。

最后一個系統(tǒng)調(diào)用是 fcntl,它用來鎖定和解鎖文件,應(yīng)用共享鎖和互斥鎖,或者是執(zhí)行一些文件相關(guān)的其他操作。

現(xiàn)在我們來關(guān)心一下和整體目錄和文件系統(tǒng)相關(guān)的系統(tǒng)調(diào)用,而不是把精力放在單個的文件上,下面列出了這些系統(tǒng)調(diào)用,我們一起來看一下。

系統(tǒng)調(diào)用描述
s = mkdir(path,mode)創(chuàng)建一個新的目錄
s = rmdir(path)移除一個目錄
s = link(oldpath,newpath)創(chuàng)建指向已有文件的鏈接
s = unlink(path)取消文件的鏈接
s = chdir(path)改變工作目錄
dir = opendir(path)打開一個目錄讀取
s = closedir(dir)關(guān)閉一個目錄
dirent = readdir(dir)讀取一個目錄項
rewinddir(dir)回轉(zhuǎn)目錄使其在此使用

可以使用 mkdir 和 rmdir 創(chuàng)建和刪除目錄。但是需要注意,只有目錄為空時才可以刪除。

創(chuàng)建一個指向已有文件的鏈接時會創(chuàng)建一個目錄項(directory entry)。系統(tǒng)調(diào)用 link 來創(chuàng)建鏈接,oldpath  代表已有的路徑,newpath 代表需要鏈接的路徑,使用 unlink 可以刪除目錄項。當(dāng)文件的最后一個鏈接被刪除時,這個文件會被自動刪除。

使用 chdir 系統(tǒng)調(diào)用可以改變工作目錄。

最后四個系統(tǒng)調(diào)用是用于讀取目錄的。和普通文件類似,他們可以被打開、關(guān)閉和讀取。每次調(diào)用 readdir  都會以固定的格式返回一個目錄項。用戶不能對目錄執(zhí)行寫操作,但是可以使用 creat 或者 link 在文件夾中創(chuàng)建一個目錄,或使用 unlink  刪除一個目錄。用戶不能在目錄中查找某個特定文件,但是可以使用 rewindir 作用于一個打開的目錄,使他能在此從頭開始讀取。

Linux 文件系統(tǒng)的實現(xiàn)

下面我們主要討論一下 虛擬文件系統(tǒng)(Virtual File System)。VFS 對高層進程和應(yīng)用程序隱藏了 Linux  支持的所有文件系統(tǒng)的區(qū)別,以及文件系統(tǒng)是存儲在本地設(shè)備,還是需要通過網(wǎng)絡(luò)訪問遠(yuǎn)程設(shè)備。設(shè)備和其他特殊文件和 VFS 層相關(guān)聯(lián)。接下來,我們就會探討一下第一個  Linux 廣泛傳播的文件系統(tǒng):ext2。隨后,我們就會探討 ext4 文件系統(tǒng)所做的改進。各種各樣的其他文件系統(tǒng)也正在使用中。所有 Linux  系統(tǒng)都可以處理多個磁盤分區(qū),每個磁盤分區(qū)上都有不同的文件系統(tǒng)。

Linux 虛擬文件系統(tǒng)

為了能夠使應(yīng)用程序能夠在不同類型的本地或者遠(yuǎn)程設(shè)備上的文件系統(tǒng)進行交互,因為在 Linux 當(dāng)中文件系統(tǒng)千奇百種,比較常見的有  EXT3、EXT4,還有基于內(nèi)存的 ramfs、tmpfs 和基于網(wǎng)絡(luò)的 nfs,和基于用戶態(tài)的 fuse,當(dāng)然 fuse  應(yīng)該不能完全的文件系統(tǒng),只能算是一個能把文件系統(tǒng)實現(xiàn)放到用戶態(tài)的模塊,滿足了內(nèi)核文件系統(tǒng)的接口,他們都是文件系統(tǒng)的一種實現(xiàn)。對于這些文件系統(tǒng),Linux  做了一層抽象就是 VFS虛擬文件系統(tǒng),

下表總結(jié)了 VFS 支持的四個主要的文件系統(tǒng)結(jié)構(gòu)。

對象描述
超級塊特定的文件系統(tǒng)
Dentry目錄項,路徑的一個組成部分
I-node特定的文件
File跟一個進程相關(guān)聯(lián)的打開文件

超級塊(superblock) 包含了有關(guān)文件系統(tǒng)布局的重要信息,超級塊如果遭到破壞那么就會導(dǎo)致整個文件系統(tǒng)不可讀。

i-node 索引節(jié)點,包含了每一個文件的描述符。

?在 Linux 中,目錄和設(shè)備也表示為文件,因為它們具有對應(yīng)的 i-node?

超級塊和索引塊所在的文件系統(tǒng)都在磁盤上有對應(yīng)的結(jié)構(gòu)。

為了便于某些目錄操作和路徑遍歷,比如 /usr/local/cxuan,VFS 支持一個 dentry 數(shù)據(jù)結(jié)構(gòu),該數(shù)據(jù)結(jié)構(gòu)代表著目錄項。這個  dentry  數(shù)據(jù)結(jié)構(gòu)有很多東西(http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch22lev1sec7.html)這個數(shù)據(jù)結(jié)構(gòu)由文件系統(tǒng)動態(tài)創(chuàng)建。

目錄項被緩存在 dentry_cache 緩存中。例如,緩存條目會緩存 /usr 、 /usr/local  等條目。如果多個進程通過硬連接訪問相同的文件,他們的文件對象將指向此緩存中的相同條目。

最后,文件數(shù)據(jù)結(jié)構(gòu)是代表著打開的文件,也代表著內(nèi)存表示,它根據(jù) open 系統(tǒng)調(diào)用創(chuàng)建。它支持 「read、write、sendfile、lock」  和其他在我們之前描述的系統(tǒng)調(diào)用中。

在 VFS 下實現(xiàn)的實際文件系統(tǒng)不需要在內(nèi)部使用完全相同的抽象和操作。但是,它們必須在語義上實現(xiàn)與 VFS 對象指定的文件系統(tǒng)操作相同的文件系統(tǒng)操作。四個  VFS 對象中每個對象的操作數(shù)據(jù)結(jié)構(gòu)的元素都是指向基礎(chǔ)文件系統(tǒng)中功能的指針。

Linux Ext2 文件系統(tǒng)

現(xiàn)在我們一起看一下 Linux 中最流行的一個磁盤文件系統(tǒng),那就是 ext2 。Linux 的第一個版本用于 MINIX1  文件系統(tǒng),它的文件名大小被限制為最大 64 MB。MINIX 1 文件系統(tǒng)被永遠(yuǎn)的被它的擴展系統(tǒng) ext 取代,因為 ext 允許更長的文件名和文件大小。由于  ext 的性能低下,ext 被其替代者 ext2 取代,ext2 目前仍在廣泛使用。

一個 ext2 Linux 磁盤分區(qū)包含了一個文件系統(tǒng),這個文件系統(tǒng)的布局如下所示

Linux文件系統(tǒng)基本概念是什么

Boot 塊也就是第 0 塊不是讓 Linux 使用的,而是用來加載和引導(dǎo)計算機啟動代碼的。在塊 0  之后,磁盤分區(qū)被分成多個組,這些組與磁盤柱面邊界所處的位置無關(guān)。

第一個塊是 超級塊(superblock)。它包含有關(guān)文件系統(tǒng)布局的信息,包括 i-node、磁盤塊數(shù)量和以及空閑磁盤塊列表的開始。下一個是  組描述符(group descriptor),其中包含有關(guān)位圖的位置,組中空閑塊和 i-node 的數(shù)量以及組中的目錄數(shù)量的信息。這些信息很重要,因為 ext2  會在磁盤上均勻分布目錄。

圖中的兩個位圖用來記錄空閑塊和空閑 i-node,這是從 MINIX 1文件系統(tǒng)繼承的選擇,大多數(shù) UNIX  文件系統(tǒng)使用位圖而不是空閑列表。每個位圖的大小是一個塊。如果一個塊的大小是 1 KB,那么就限制了塊組的數(shù)量是 8192 個塊和 8192 個  i-node。塊的大小是一個嚴(yán)格的限制,塊組的數(shù)量不固定,在 4KB 的塊中,塊組的數(shù)量增大四倍。

在超級塊之后分布的是 i-node 它們自己,i-node 取值范圍是 1 - 某些最大值。每個 i-node 是 128 字節(jié)的 long  ,這些字節(jié)恰好能夠描述一個文件。i-node 包含了統(tǒng)計信息(包含了 stat 系統(tǒng)調(diào)用能獲得的所有者信息,實際上 stat 就是從 i-node  中讀取信息的),以及足夠的信息來查找保存文件數(shù)據(jù)的所有磁盤塊。

在 i-node 之后的是 數(shù)據(jù)塊(data  blocks)。所有的文件和目錄都保存在這。如果一個文件或者目錄包含多個塊,那么這些塊在磁盤中的分布不一定是連續(xù)的,也有可能不連續(xù)。事實上,大文件塊可能會被拆分成很多小塊散布在整個磁盤上。

對應(yīng)于目錄的 i-node 分散在整個磁盤組上。如果有足夠的空間,ext2 會把普通文件組織到與父目錄相同的塊組中,而把同一塊上的數(shù)據(jù)文件組織成初始  i-node 節(jié)點。位圖用來快速確定新文件系統(tǒng)數(shù)據(jù)的分配位置。在分配新的文件塊時,ext2  也會給該文件預(yù)分配許多額外的數(shù)據(jù)塊,這樣可以減少將來向文件寫入數(shù)據(jù)時產(chǎn)生的文件碎片。這種策略在整個磁盤上實現(xiàn)了文件系統(tǒng)的  負(fù)載,后續(xù)還有對文件碎片的排列和整理,而且性能也比較好。

為了達到訪問的目的,需要首先使用 Linux 系統(tǒng)調(diào)用,例如 open,這個系統(tǒng)調(diào)用會確定打開文件的路徑。路徑分為兩種,相對路徑 和  絕對路徑。如果使用相對路徑,那么就會從當(dāng)前目錄開始查找,否則就會從根目錄進行查找。

目錄文件的文件名最高不能超過 255 個字符,它的分配如下圖所示

Linux文件系統(tǒng)基本概念是什么

每一個目錄都由整數(shù)個磁盤塊組成,這樣目錄就可以整體的寫入磁盤。在一個目錄中,文件和子目錄的目錄項都是未經(jīng)排序的,并且一個挨著一個。目錄項不能跨越磁盤塊,所以通常在每個磁盤塊的尾部會有部分未使用的字節(jié)。

上圖中每個目錄項都由四個固定長度的屬性和一個長度可變的屬性組成。第一個屬性是 i-node 節(jié)點數(shù)量,文件 first 的 i-node 編號是 19  ,文件 second 的編號是 42,目錄 third 的 i-node 編號是 88。緊隨其后的是  rec_len域,表明目錄項大小是多少字節(jié),名稱后面會有一些擴展,當(dāng)名字以未知長度填充時,這個域被用來尋找下一個目錄項,直至最后的未使用。這也是圖中箭頭的含義。緊隨其后的是  類型域:F 表示的是文件,D 表示的是目錄,最后是固定長度的文件名,上面的文件名的長度依次是 5、6、5,最后以文件名結(jié)束。

rec_len 域是如何擴展的呢?如下圖所示

Linux文件系統(tǒng)基本概念是什么

我們可以看到,中間的 second 被移除了,所以將其所在的域變?yōu)榈谝粋€目錄項的填充。當(dāng)然,這個填充可以作為后續(xù)的目錄項。

由于目錄是按照線性的順序進行查找的,因此可能需要很長時間才能在大文件末尾找到目錄項。因此,系統(tǒng)會為近期的訪問目錄維護一個緩存。這個緩存用文件名來查找,如果緩存命中,那么就會避免線程搜索這樣昂貴的開銷。組成路徑的每個部分都在目錄緩存中保存一個  dentry 對象,并且通過 i-node 找到后續(xù)的路徑元素的目錄項,直到找到真正的文件 i - node。

比如說要使用絕對路徑來尋找一個文件,我們暫定這個路徑是 /usr/local/file,那么需要經(jīng)過如下幾個步驟:

首先,系統(tǒng)會確定根目錄,它通常使用 2 號 i -node ,也就是索引 2 節(jié)點,因為索引節(jié)點 1 是 ext2 /3/4  文件系統(tǒng)上的壞塊索引節(jié)點。系統(tǒng)會將一項放在 dentry 緩存中,以應(yīng)對將來對根目錄的查找。

然后,在根目錄中查找字符串 usr,得到 /usr 目錄的 i - node 節(jié)點號。/usr 的 i - node 同樣也進入 dentry  緩存。然后節(jié)點被取出,并從中解析出磁盤塊,這樣就可以讀取 /usr 目錄并查找字符串 local 了。一旦找到這個目錄項,目錄 /usr/local 的 i -  node 節(jié)點就可以從中獲得。有了 /usr/local 的 i - node 節(jié)點號,就可以讀取 i - node 并確定目錄所在的磁盤塊。最后,從  /usr/local 目錄查找 file 并確定其 i - node 節(jié)點呢號。

如果文件存在,那么系統(tǒng)會提取 i - node 節(jié)點號并把它作為索引在 i - node 節(jié)點表中定位相應(yīng)的 i - node 節(jié)點并裝入內(nèi)存。i -  node 被存放在 i - node 節(jié)點表(i-node table) 中,節(jié)點表是一個內(nèi)核數(shù)據(jù)結(jié)構(gòu),它會持有當(dāng)前打開文件和目錄的 i - node  節(jié)點號。下面是一些 Linux 文件系統(tǒng)支持的 i - node 數(shù)據(jù)結(jié)構(gòu)。

屬性字節(jié)描述
Mode2文件屬性、保護位、setuid 和 setgid 位
Nlinks2指向 i - node 節(jié)點目錄項的數(shù)目
Uid2文件所有者的 UID
Gid2文件所有者的 GID
Size4文件字節(jié)大小
Addr6012 個磁盤塊以及后面 3 個間接塊的地址
Gen1每次重復(fù)使用 i - node 時增加的代號
Atime4最近訪問文件的時間
Mtime4最近修改文件的時間
Ctime4最近更改 i - node 的時間

現(xiàn)在我們來一起探討一下文件讀取過程,還記得 read 函數(shù)是如何調(diào)用的嗎?

n = read(fd,buffer,nbytes);

當(dāng)內(nèi)核接管后,它會從這三個參數(shù)以及內(nèi)部表與用戶有關(guān)的信息開始。內(nèi)部表的其中一項是文件描述符數(shù)組。文件描述符數(shù)組用文件描述符  作為索引并為每一個打開文件保存一個表項。

文件是和 i - node 節(jié)點號相關(guān)的。那么如何通過一個文件描述符找到文件對應(yīng)的 i - node 節(jié)點呢?

這里使用的一種設(shè)計思想是在文件描述符表和 i - node 節(jié)點表之間插入一個新的表,叫做 打開文件描述符(open-file-description  table)。文件的讀寫位置會在打開文件描述符表中存在,如下圖所示

Linux文件系統(tǒng)基本概念是什么

我們使用 shell 、P1 和 P2 來描述一下父進程、子進程、子進程的關(guān)系。Shell 首先生成 P1,P1 的數(shù)據(jù)結(jié)構(gòu)就是 Shell  的一個副本,因此兩者都指向相同的打開文件描述符的表項。當(dāng) P1 運行完成后,Shell 的文件描述符仍會指向 P1 文件位置的打開文件描述。然后 Shell  生成了 P2,新的子進程自動繼承文件的讀寫位置,甚至 P2 和 Shell 都不知道文件具體的讀寫位置。

上面描述的是父進程和子進程這兩個 相關(guān)  進程,如果是一個不相關(guān)進程打開文件時,它將得到自己的打開文件描述符表項,以及自己的文件讀寫位置,這是我們需要的。

?因此,打開文件描述符相當(dāng)于是給相關(guān)進程提供同一個讀寫位置,而給不相關(guān)進程提供各自私有的位置。?

i - node 包含三個間接塊的磁盤地址,它們每個指向磁盤塊的地址所能夠存儲的大小不一樣。

Linux Ext4 文件系統(tǒng)

為了防止由于系統(tǒng)崩潰和電源故障造成的數(shù)據(jù)丟失,ext2  系統(tǒng)必須在每個數(shù)據(jù)塊創(chuàng)建之后立即將其寫入到磁盤上,磁盤磁頭尋道操作導(dǎo)致的延遲是無法讓人忍受的。為了增強文件系統(tǒng)的健壯性,Linux 依靠日志文件系統(tǒng),ext3  是一個日志文件系統(tǒng),它在 ext2 文件系統(tǒng)的基礎(chǔ)之上做了改進,ext4 也是 ext3 的改進,ext4 也是一個日志文件系統(tǒng)。ext4 改變了 ext3  的塊尋址方案,從而支持更大的文件和更大的文件系統(tǒng)大小。下面我們就來描述一下 ext4 文件系統(tǒng)的特性。

具有記錄的文件系統(tǒng)最基本的功能就是記錄日志,這個日志記錄了按照順序描述所有文件系統(tǒng)的操作。通過順序?qū)懗鑫募到y(tǒng)數(shù)據(jù)或元數(shù)據(jù)的更改,操作不受磁盤訪問期間磁盤頭移動的開銷。最終,這個變更會寫入并提交到合適的磁盤位置上。如果這個變更在提交到磁盤前文件系統(tǒng)宕機了,那么在重啟期間,系統(tǒng)會檢測到文件系統(tǒng)未正確卸載,那么就會遍歷日志并應(yīng)用日志的記錄來對文件系統(tǒng)進行更改。

Ext4 文件系統(tǒng)被設(shè)計用來高度匹配 ext2 和 ext3 文件系統(tǒng)的,盡管 ext4  文件系統(tǒng)在內(nèi)核數(shù)據(jù)結(jié)構(gòu)和磁盤布局上都做了變更。盡管如此,一個文件系統(tǒng)能夠從 ext2 文件系統(tǒng)上卸載后成功的掛載到 ext4  文件系統(tǒng)上,并提供合適的日志記錄。

日志是作為循環(huán)緩沖區(qū)管理的文件。日志可以存儲在與主文件系統(tǒng)相同或者不同的設(shè)備上。日志記錄的讀寫操作會由單獨的 JBD(Journaling Block  Device) 來扮演。

JBD 中有三個主要的數(shù)據(jù)結(jié)構(gòu),分別是 「log  record(日志記錄)、原子操作和事務(wù)」。一個日志記錄描述了一個低級別的文件系統(tǒng)操作,這個操作通常導(dǎo)致塊內(nèi)的變化。因為像是 write  這種系統(tǒng)調(diào)用會包含多個地方的改動 --- i - node 節(jié)點,現(xiàn)有的文件塊,新的文件塊和空閑列表等。相關(guān)的日志記錄會以原子性的方式分組。ext4  會通知系統(tǒng)調(diào)用進程的開始和結(jié)束,以此使 JBD 能夠確保原子操作的記錄都能被應(yīng)用,或者一個也不被應(yīng)用。最后,主要從效率方面考慮,JBD  會視原子操作的集合為事務(wù)。一個事務(wù)中的日志記錄是連續(xù)存儲的。只有在所有的變更一起應(yīng)用到磁盤后,日志記錄才能夠被丟棄。

由于為每個磁盤寫出日志的開銷會很大,所以 ext4  可以配置為保留所有磁盤更改的日志,或者僅僅保留與文件系統(tǒng)元數(shù)據(jù)相關(guān)的日志更改。僅僅記錄元數(shù)據(jù)可以減少系統(tǒng)開銷,提升性能,但不能保證不會損壞文件數(shù)據(jù)。其他的幾個日志系統(tǒng)維護著一系列元數(shù)據(jù)操作的日志,例如  SGI 的 XFS。

/proc 文件系統(tǒng)

另外一個 Linux 文件系統(tǒng)是 /proc (process) 文件系統(tǒng)

?它的主要思想來源于貝爾實驗室開發(fā)的第 8 版的 UNIX,后來被 BSD 和 System V 采用。?

然而,Linux 在一些方面上對這個想法進行了擴充。它的基本概念是為系統(tǒng)中的每個進程在 /proc 中創(chuàng)建一個目錄。目錄的名字就是進程  PID,以十進制數(shù)進行表示。例如,/proc/1024 就是一個進程號為 1024  的目錄。在該目錄下是進程信息相關(guān)的文件,比如進程的命令行、環(huán)境變量和信號掩碼等。事實上,這些文件在磁盤上并不存在磁盤中。當(dāng)需要這些信息的時候,系統(tǒng)會按需從進程中讀取,并以標(biāo)準(zhǔn)格式返回給用戶。

許多 Linux 擴展與 /proc 中的其他文件和目錄有關(guān)。它們包含各種各樣的關(guān)于  CPU、磁盤分區(qū)、設(shè)備、中斷向量、內(nèi)核計數(shù)器、文件系統(tǒng)、已加載模塊等信息。非特權(quán)用戶可以讀取很多這樣的信息,于是就可以通過一種安全的方式了解系統(tǒng)情況。

NFS 網(wǎng)絡(luò)文件系統(tǒng)

從一開始,網(wǎng)絡(luò)就在 Linux 中扮演了很重要的作用。下面我們會探討一下 NFS(Network File System) 網(wǎng)絡(luò)文件系統(tǒng),它在現(xiàn)代  Linux 操作系統(tǒng)的作用是將不同計算機上的不同文件系統(tǒng)鏈接成一個邏輯整體。

NFS 架構(gòu)NFS 最基本的思想是允許任意選定的一些客戶端和服務(wù)器共享一個公共文件系統(tǒng)。在許多情況下,所有的客戶端和服務(wù)器都會在同一個 LAN(Local  Area Network)  局域網(wǎng)內(nèi)共享,但是這并不是必須的。也可能是下面這樣的情況:如果客戶端和服務(wù)器距離較遠(yuǎn),那么它們也可以在廣域網(wǎng)上運行??蛻舳丝梢允欠?wù)器,服務(wù)器可以是客戶端,但是為了簡單起見,我們說的客戶端就是消費服務(wù),而服務(wù)器就是提供服務(wù)的角度來聊。

每一個 NFS  服務(wù)都會導(dǎo)出一個或者多個目錄供遠(yuǎn)程客戶端訪問。當(dāng)一個目錄可用時,它的所有子目錄也可用。因此,通常整個目錄樹都會作為一個整體導(dǎo)出。服務(wù)器導(dǎo)出的目錄列表會用一個文件來維護,這個文件是  /etc/exports,當(dāng)服務(wù)器啟動后,這些目錄可以自動的被導(dǎo)出。客戶端通過掛載這些導(dǎo)出的目錄來訪問它們。當(dāng)一個客戶端掛載了一個遠(yuǎn)程目錄,這個目錄就成為客戶端目錄層次的一部分,如下圖所示。

Linux文件系統(tǒng)基本概念是什么

在這個示例中,一號客戶機掛載到服務(wù)器的 bin 目錄下,因此它現(xiàn)在可以使用 shell 訪問 /bin/cat 或者其他任何一個目錄。同樣,客戶機 1  也可以掛載到 二號服務(wù)器上從而訪問 /usr/local/projects/proj1 或者其他目錄。二號客戶機同樣可以掛載到二號服務(wù)器上,訪問路徑是  /mnt/projects/proj2。

從上面可以看到,由于不同的客戶端將文件掛載到各自目錄樹的不同位置,同一個文件在不同的客戶端有不同的訪問路徑和不同的名字。掛載點一般通常在客戶端本地,服務(wù)器不知道任何一個掛載點的存在。

NFS 協(xié)議

由于 NFS 的協(xié)議之一是支持 異構(gòu)  系統(tǒng),客戶端和服務(wù)器可能在不同的硬件上運行不同的操作系統(tǒng),因此有必要在服務(wù)器和客戶端之間進行接口定義。這樣才能讓任何寫一個新客戶端能夠和現(xiàn)有的服務(wù)器一起正常工作,反之亦然。

NFS 就通過定義兩個客戶端 - 服務(wù)器協(xié)議從而實現(xiàn)了這個目標(biāo)。協(xié)議就是客戶端發(fā)送給服務(wù)器的一連串的請求,以及服務(wù)器發(fā)送回客戶端的相應(yīng)答復(fù)。

第一個 NFS  協(xié)議是處理掛載??蛻舳丝梢韵蚍?wù)器發(fā)送路徑名并且請求服務(wù)器是否能夠?qū)⒎?wù)器的目錄掛載到自己目錄層次上。因為服務(wù)器不關(guān)心掛載到哪里,因此請求不會包含掛載地址。如果路徑名是合法的并且指定的目錄已經(jīng)被導(dǎo)出,那么服務(wù)器會將文件  句柄 返回給客戶端。

?文件句柄包含唯一標(biāo)識文件系統(tǒng)類型,磁盤,目錄的i節(jié)點號和安全性信息的字段。?

隨后調(diào)用讀取和寫入已安裝目錄或其任何子目錄中的文件,都將使用文件句柄。

當(dāng) Linux 啟動時會在多用戶之前運行 shell 腳本 /etc/rc  ??梢詫燧d遠(yuǎn)程文件系統(tǒng)的命令寫入該腳本中,這樣就可以在允許用戶登陸之前自動掛載必要的遠(yuǎn)程文件系統(tǒng)。大部分 Linux  版本是支持自動掛載的。這個特性會支持將遠(yuǎn)程目錄和本地目錄進行關(guān)聯(lián)。

相對于手動掛載到 /etc/rc 目錄下,自動掛載具有以下優(yōu)勢

  • 如果列出的 /etc/rc  目錄下出現(xiàn)了某種故障,那么客戶端將無法啟動,或者啟動會很困難、延遲或者伴隨一些出錯信息,如果客戶根本不需要這個服務(wù)器,那么手動做了這些工作就白費了。

  • 允許客戶端并行的嘗試一組服務(wù)器,可以實現(xiàn)一定程度的容錯率,并且性能也可以得到提高。

另一方面,我們默認(rèn)在自動掛載時所有可選的文件系統(tǒng)都是相同的。由于 NFS  不提供對文件或目錄復(fù)制的支持,用戶需要自己確保這些所有的文件系統(tǒng)都是相同的。因此,大部分的自動掛載都只應(yīng)用于二進制文件和很少改動的只讀的文件系統(tǒng)。

第二個 NFS  協(xié)議是為文件和目錄的訪問而設(shè)計的。客戶端能夠通過向服務(wù)器發(fā)送消息來操作目錄和讀寫文件。客戶端也可以訪問文件屬性,比如文件模式、大小、上次修改時間。NFS  支持大多數(shù)的 Linux 系統(tǒng)調(diào)用,但是 open 和 close 系統(tǒng)調(diào)用卻不支持。

?不支持 open 和 close 并不是一種疏忽,而是一種刻意的設(shè)計,完全沒有必要在讀一個文件之前對其進行打開,也沒有必要在讀完時對其進行關(guān)閉。?

NFS 使用了標(biāo)準(zhǔn)的 UNIX 保護機制,使用 rwx 位來標(biāo)示所有者(owner)、組(groups)、其他用戶 。最初,每個請求消息都會攜帶調(diào)用者的  groupId 和 userId,NFS  會對其進行驗證。事實上,它會信任客戶端不會發(fā)生欺騙行為??梢允褂霉€密碼來創(chuàng)建一個安全密鑰,在每次請求和應(yīng)答中使用它驗證客戶端和服務(wù)器。

NFS 實現(xiàn)

即使客戶端和服務(wù)器的代碼實現(xiàn)是獨立于 NFS 協(xié)議的,大部分的 Linux 系統(tǒng)會使用一個下圖的三層實現(xiàn),頂層是系統(tǒng)調(diào)用層,系統(tǒng)調(diào)用層能夠處理  open 、 read 、 close 這類的系統(tǒng)調(diào)用。在解析和參數(shù)檢查結(jié)束后調(diào)用第二層,虛擬文件系統(tǒng) (VFS) 層。

Linux文件系統(tǒng)基本概念是什么

VFS 層的任務(wù)是維護一個表,每個已經(jīng)打開的文件都在表中有一個表項。VFS 層為每一個打開的文件維護著一個虛擬i節(jié)點,簡稱為 v - node。v  節(jié)點用來說明文件是本地文件還是遠(yuǎn)程文件。如果是遠(yuǎn)程文件的話,那么 v - node  會提供足夠的信息使客戶端能夠訪問它們。對于本地文件,會記錄其所在的文件系統(tǒng)和文件的 i-node ,因為現(xiàn)代操作系統(tǒng)能夠支持多文件系統(tǒng)。雖然 VFS 是為了支持  NFS 而設(shè)計的,但是現(xiàn)代操作系統(tǒng)都會使用 VFS,而不管有沒有 NFS。

感謝各位的閱讀,以上就是“Linux文件系統(tǒng)基本概念是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Linux文件系統(tǒng)基本概念是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

當(dāng)前標(biāo)題:Linux文件系統(tǒng)基本概念是什么
網(wǎng)站URL:http://www.muchs.cn/article4/ghjgie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計公司、標(biāo)簽優(yōu)化、企業(yè)網(wǎng)站制作響應(yīng)式網(wǎng)站、用戶體驗

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)