Linux 操作系統原理 — 文件系統 — 虛擬文件系統
目錄
文章目錄
目錄
為什么需要文件系統?
linux 的虛擬文件系統
創建 linux 文件系統
為什么需要文件系統?
程序 = 數據結構 + 算法,所有的應用程序都需要存儲和檢索信息,進程運行時它能夠在內存空間內存儲一定量的信息。然而,存儲的容量受到進程的用戶態虛擬內存空間大小的限制。用戶進程的數據需要持久化在擁有更大容量的外存(磁盤)空間。
磁盤(Magnetic disk)一直以來都是持久化數據的設備,理論上,只要有了讀寫操作就能解決持久化數據存取的問題。但事實上,磁盤需要支持更多的操作,特別是在多程序運行的大型系統上(如服務器)。在這種情況下,很容易產生一些問題,例如:
你如何找到這些信息?
你如何保證一個用戶不會讀取另外一個用戶的數據?
你怎么知道哪些塊是空閑的?
為了解決浙西問題,UNIX 設計者提出一個新的抽象 - 文件。在 UNIX-like 操作系統一致秉承著 一切皆文件 的設計理念。
文件(Files)是由進程創建的邏輯信息單元。一個磁盤會包含成百上千萬個文件。進程能夠讀取已存在的文件,并在需要時修改它們。存儲在文件中的信息必須是持久的,這也就是說,不會因為進程的創建和終止而受影響。一個文件只能在當用戶明確刪除的時候才能消失。文件由操作系統進行管理,有關文件的構造、命名、訪問、使用、保護、實現和管理方式都是操作系統設計的主要內容。
事實上,如果你能把每個文件都看作一個獨立的地址空間,那么你真正理解了文件的概念。操作系統中處理文件的部分稱為文件系統(File system)。
Linux 的虛擬文件系統
文件系統是對一個存儲設備上的數據和元數據進行組織的機制。由于定義如此寬泛,所以 Linux 文件系統的接口實現采用了分層的體系結構:將用戶接口層、文件系統實現和操作存儲設備的驅動程序分隔開,從而構成了一個虛擬文件系統(Virtual File System,VFS)。
在同一操作系統下,可能會使用到不同的文件系統。在計算機世界中,任何問題都可以添加一個層級來加個代理來解決。UNIX 操作系統通過虛擬文件系統來將多種文件系統構成一個有序的結構。其關鍵思想是:抽象出所有文件系統都共有的部分,并將這部分代碼放在一層,這一層再調用具體文件系統來管理數據。
Linux 使用最普遍的文件系統是 ExtX,也能夠支持 FAT、 FAT32、 VFAT 和 ISO9660 等不同類型的文件系統,從而可以方便地和其它操作系統交換數據。
ext2:早期 Linux 中常用的文件系統。
ext3:ext2 的升級版,帶有日志功能。
ext4:較新的文件系統版本。
RAMFS:內存文件系統,速度很快。
VFS 隱藏了各種硬件的具體細節,把文件系統操作和不同文件系統的具體實現細節分離了開來,為所有的設備提供了統一的接口,VFS 提供了多達數十種不同的文件系統。VFS 可以分為邏輯文件系統和設備驅動程序:
邏輯文件系統指 Linux 所支持的文件系統,如 extX、FAT 等。
設備驅動程序指為每一種硬件控制器所編寫的設備驅動程序模塊。
VFS 對用戶進程提供一個 “上層” 接口,這個接口就是著名的 POSIX 接口。這些來自用戶進程的調用,都是標準的 POSIX 系統調用,比如 open、read、write 和 seek 等。VFS 也有一個對于實際文件系統的 “下層” 接口,包含了許多針對特定文件系統的功能調用。
用戶空間包含一些應用程序(例如,文件系統的使用者)和 GNU C 庫(glibc),它們為文件系統調用(打開、讀取、寫和關閉)提供用戶接口。系統調用接口的作用就像是交換器,它將系統調用從用戶空間發送到內核空間中的適當端點。
VFS 是底層文件系統的主要接口。這個組件導出一組接口,然后將它們抽象到各個文件系統,各個文件系統的行為可能差異很大。有兩個針對文件系統對象的緩存(inode 和 dentry)。它們緩存最近使用過的文件系統對象。
當系統啟動時,根文件系統在 VFS 中注冊。另外,當裝載其他文件系統時,不管在啟動時還是在操作過程中,它們也必須在 VFS 中注冊。另外,在引導時或操作期間掛載其他文件系統時,它們也必須向 VFS 注冊。當文件系統注冊時,其基本作用是提供 VFS 所需功能的地址列表、調用向量表、或者 VFS 對象。因此一旦文件系統注冊到 VFS,它就知道從哪里開始讀取數據塊。
裝載文件系統后就可以使用它了。比如,如果一個文件系統裝載到 /usr 并且一個進程調用它:
open("/usr/include/unistd.h", O_RDONLY)
1
當解析路徑時, VFS 看到新的文件系統被掛載到 /usr,并且通過搜索已經裝載文件系統的超級塊來確定它的超塊。然后它找到它所轉載的文件的根目錄,在那里查找路徑 include/unistd.h。然后 VFS 創建一個 vnode 并調用實際文件系統,以返回所有的在文件 inode 中的信息。這個信息和其他信息一起復制到 vnode (內存中)。而這些其他信息中最重要的是指向包含調用 vnode 操作的函數表的指針,比如 read、write 和 close 等。
當 vnode 被創建后,為了進程調用,VFS 在文件描述符表中創建一個表項,并將它指向新的 vnode,最后,VFS 向調用者返回文件描述符,所以調用者可以用它去 read、write 或者 close 文件。
當進程用文件描述符進行一個讀操作時,VFS 通過進程表和文件描述符確定 vnode 的位置,并跟隨指針指向函數表,這樣就調用了處理 read 函數,運行在實際系統中的代碼并得到所請求的塊。VFS 不知道請求時來源于本地硬盤、還是來源于網絡中的遠程文件系統、CD-ROM 、USB 或者其他介質,所有相關的數據結構如下圖所示:從調用者進程號和文件描述符開始,進而是 vnode,讀函數指針,然后是對實際文件系統的訪問函數定位。
創建 Linux 文件系統
創建一個經過初始化的文件:
$ dd if=/dev/zero of=file.img bs=1k count=10000 10000+0 records in 10000+0 records out
1
2
3
現在有了一個 10MB 的 file.img 文件。使用 losetup 命令將一個循環設備與這個文件關聯起來,讓它看起來像一個塊設備,而不是文件系統中的常規文件:
$ losetup /dev/loop0 file.img
1
這個文件現在作為一個塊設備出現(由 /dev/loop0 表示)。然后用 mke2fs 在這個設備上創建一個文件系統。這個命令創建一個指定大小的新的 ext2 文件系統:
$ mke2fs -c /dev/loop0 10000 mke2fs 1.35 (28-Feb-2004) max_blocks 1024000, rsv_groups = 1250, rsv_gdb = 39 Filesystem label= OS type: Linux Block size=1024 (log=0) Fragment size=1024 (log=0) 2512 inodes, 10000 blocks 500 blocks (5.00%) reserved for the super user ...
1
2
3
4
5
6
7
8
9
10
使用 mount 命令將循環設備(/dev/loop0)所表示的 file.img 文件掛裝到掛裝點 /mnt/point1。注意,文件系統類型指定為 ext2:
$ mkdir /mnt/point1 $ mount -t ext2 /dev/loop0 /mnt/point1
1
2
還可以繼續這個過程:在剛才掛裝的文件系統中創建一個新文件,將它與一個循環設備關聯起來,再在上面創建另一個文件系統。
$ dd if=/dev/zero of=/mnt/point1/file.img bs=1k count=1000 1000+0 records in 1000+0 records out $ losetup /dev/loop1 /mnt/point1/file.img $ mke2fs -c /dev/loop1 1000 mke2fs 1.35 (28-Feb-2004) max_blocks 1024000, rsv_groups = 125, rsv_gdb = 3 Filesystem label= ... $ mkdir /mnt/point2 $ mount -t ext2 /dev/loop1 /mnt/point2 $ ls /mnt/point2 lost+found $ ls /mnt/point1 file.img lost+found
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
通過這個簡單的演示很容易體會到 Linux 文件系統(和循環設備)是多么強大。可以按照相同的方法在文件上用循環設備創建加密的文件系統??梢栽谛枰獣r使用循環設備臨時掛裝文件,這有助于保護數據。
Linux 虛擬化
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。