準備了很久,找了好多天資料,還不知道應(yīng)該如何動筆寫:因為擔心拿捏不住,所以一方面繼續(xù)查找資料,一方面思考如何來寫。作為《Shell編程范例》的一部分,希望它能夠很好地幫助 Shell 程序員理解如何用 Shell 命令來完成和 Linux 系統(tǒng)關(guān)系非常大的文件系統(tǒng)的各種操作,希望讓 Shell 程序員中對文件系統(tǒng)"混沌"的狀態(tài)從此消失,希望文件系統(tǒng)以一種更為清晰的樣子呈現(xiàn)在眼前。
如何來認識文件系統(tǒng)呢?從 Shell 程序員的角度來看,文件系統(tǒng)就是一個用來組織各種文件的方法。但是文件系統(tǒng)無法獨立于硬件存儲設(shè)備和操作系統(tǒng)而存在,因此還是有必要來弄清楚硬件存儲設(shè)備、分區(qū)、操作系統(tǒng)、邏輯卷、文件系統(tǒng)等各種概念之間的聯(lián)系,以便理解文件系統(tǒng)常規(guī)操作的一些“細節(jié)”。這個聯(lián)系或許(也許會有一些問題)可以通過這樣一種方式來呈現(xiàn):
從圖中可以清晰地看到各個“概念”之間的關(guān)系,它們以不同層次分布,覆蓋硬件設(shè)備、系統(tǒng)內(nèi)核空間、系統(tǒng)用戶空間。在用戶空間,用戶可以不管內(nèi)核如何操作具體硬件設(shè)備,僅僅使用程序員設(shè)計的各種界面就可以,而普通程序員也僅僅需要利用內(nèi)核提供的各種接口(System Call)或者一些C庫來和內(nèi)核進行交互,而無須關(guān)心具體的實現(xiàn)細節(jié)。不過對于操作系統(tǒng)開發(fā)人員,他們需要在內(nèi)核空間設(shè)計特定的數(shù)據(jù)結(jié)構(gòu)來管理和組織底層的硬件設(shè)備。
下面從下到上的方式(即從底層硬件開始),用工具來分析和理解圖中幾個重要概念。(如果有興趣,可以先看看下面的幾則資料)
參考資料:
Linux 系統(tǒng)通過設(shè)備驅(qū)動管理硬件設(shè)備。如果添加了新的硬件設(shè)備,那么需要編寫相應(yīng)的硬件驅(qū)動來管理它。對于一些常見的硬件設(shè)備,系統(tǒng)已經(jīng)自帶了相應(yīng)的驅(qū)動,編譯內(nèi)核時,選中它們,然后編譯成內(nèi)核的一部分或者以模塊的方式編譯。如果以模塊的方式編譯,那么可以在系統(tǒng)的 /lib/modules/$(uname -r)
目錄下找到對應(yīng)的模塊文件。
比如,可以這樣找到相應(yīng)的 scsi 驅(qū)動和 usb 驅(qū)動對應(yīng)的模塊文件:
更新系統(tǒng)中文件索引數(shù)據(jù)庫(有點慢)
$ updatedb
查找 scsi 相關(guān)的驅(qū)動
$ locate scsi*.ko
查找 usb 相關(guān)的驅(qū)動
$ locate usb*.ko
這些驅(qū)動以 .ko
為后綴,在安裝系統(tǒng)時默認編譯為了模塊。實際上可以把它們編譯為內(nèi)核的一部分,僅僅需要在編譯內(nèi)核時選擇為[*]
即可。但是,很多情況下會以模塊的方式編譯它們,這樣可以減少內(nèi)核的大小,并根據(jù)需要靈活地加載和卸載它們。下面簡單地演示如何卸載模塊、加載模塊以及查看已加載模塊的狀態(tài)。
可通過 /proc
文件系統(tǒng)的 modules
文件檢查內(nèi)核中已加載的各個模塊的狀態(tài),也可以通過 lsmod
命令直接查看它們。
$ cat /proc/modules
或者
$ lsmod
查看 scsi 和 usb 相關(guān)驅(qū)動,結(jié)果各列為模塊名、模塊大小、被其他模塊的引用情況(引用次數(shù)、引用它們的模塊)
$ lsmod | egrep "scsi|usb"
usbhid 29536 0
hid 28928 1 usbhid
usbcore 138632 4 usbhid,ehci_hcd,ohci_hcd
scsi_mod 147084 4 sg,sr_mod,sd_mod,libata
下面卸載 usbhid
模塊看看(不要卸載scsi的驅(qū)動!因為你的系統(tǒng)可能就跑在上面,如果確實想玩玩,卸載前記得保存數(shù)據(jù)),通過 rmmod
命令就可以實現(xiàn),先切換到 Root 用戶:
$ sudo -s
# rmmod usbhid
再查看該模塊的信息,已經(jīng)看不到了吧
$ lsmod | grep ^usbhid
如果有個 usb 鼠標,那么移動一下,是不是發(fā)現(xiàn)動不了啦?因為設(shè)備驅(qū)動都沒有了,設(shè)備自然就沒法用羅。不過不要緊張,既然知道原因,那么重新加載驅(qū)動就可以,下面用 insmod
把 usbhid
模塊重新加載上。
$ sudo -s
# insmod `locate usbhid.ko`
locate usbhid.ko
是為了找出 usbhid.ko
模塊的路徑,如果之前沒有 updatedb
,估計用它是找不到了,不過也可以直接到 /lib/modules
目錄下用 find
把 usbhid.ko
文件找到。
# insmod $(find /lib/modules -name "*usbhid.ko*" | grep `uname -r`)
現(xiàn)在鼠標又可以用啦,不信再動一下鼠標 :-)
到這里,硬件設(shè)備和設(shè)備驅(qū)動之間關(guān)系應(yīng)該是比較清楚了。如果沒有,那么繼續(xù)下面的內(nèi)容。
Linux 設(shè)備驅(qū)動關(guān)聯(lián)著相應(yīng)的設(shè)備文件,而設(shè)備文件則和硬件設(shè)備一一對應(yīng)。這些設(shè)備文件都統(tǒng)一存放在系統(tǒng)的 /dev/
目錄下。
例如,scsi 設(shè)備對應(yīng)/dev/sda
,/dev/sda1
,/dev/sda2
... 下面查看這些設(shè)備信息。
$ ls -l /dev/sda*
brw-rw---- 1 root disk 8, 0 2007-12-28 22:49 /dev/sda
brw-rw---- 1 root disk 8, 1 2007-12-28 22:50 /dev/sda1
brw-rw---- 1 root disk 8, 3 2007-12-28 22:49 /dev/sda3
brw-rw---- 1 root disk 8, 4 2007-12-28 22:49 /dev/sda4
brw-rw---- 1 root disk 8, 5 2007-12-28 22:50 /dev/sda5
brw-rw---- 1 root disk 8, 6 2007-12-28 22:50 /dev/sda6
brw-rw---- 1 root disk 8, 7 2007-12-28 22:50 /dev/sda7
brw-rw---- 1 root disk 8, 8 2007-12-28 22:50 /dev/sda8
可以看到第一列第一個字符都是 b
,第五列都是數(shù)字 8 。 b
表示該文件是一個塊設(shè)備文件,對應(yīng)地,如果是 c
則表示字符設(shè)備(例如 `/dev/ttyS0),關(guān)于塊設(shè)備和字符設(shè)備的區(qū)別,可以看這里:
字符設(shè)備:字符設(shè)備就是能夠像字節(jié)流一樣訪問的設(shè)備,字符終端和串口就屬于字符設(shè)備。
- 塊設(shè)備:塊設(shè)備上可以容納文件系統(tǒng)。與字符設(shè)備不同,在讀寫時,塊設(shè)備每次只能傳輸一個或多個完整的塊。在 Linux 操作系統(tǒng)中,應(yīng)用程序可以像訪問字符設(shè)備一樣讀寫塊設(shè)備(一次讀取或?qū)懭肴我獾淖止?jié)數(shù)據(jù))。因此,塊設(shè)備和字符設(shè)備的區(qū)別僅僅是在內(nèi)核中對于數(shù)據(jù)的管理不同。
數(shù)字 8 則是該硬件設(shè)備在內(nèi)核中對應(yīng)的設(shè)備編號,可以在內(nèi)核的 Documentation/devices.txt
和 /proc/devices
文件中找到設(shè)備號分配情況。但是為什么同一個設(shè)備會對應(yīng)不同的設(shè)備文件(/dev/sda
后面為什么還有不同的數(shù)字,而且 ls
結(jié)果中的第 6 列和它們對應(yīng)起來)。這實際上是為了區(qū)分不同設(shè)備的不同部分。對于硬盤,這樣可以處理硬盤內(nèi)部的不同分區(qū)。就內(nèi)核而言,它僅僅需要通過第 5 列的設(shè)備號就可以找到對應(yīng)的硬件設(shè)備,但是對于驅(qū)動模塊來說,它還需要知道如何處理不同的分區(qū),于是就多了一個輔設(shè)備號,即第 6 列對應(yīng)的內(nèi)容。這樣一個設(shè)備就有了主設(shè)備號(第 5 列)和輔設(shè)備號(第 6 列),從而方便地實現(xiàn)對各種硬件設(shè)備的管理。
因為設(shè)備文件和硬件是對應(yīng)的,這樣可以直接從 /dev/sda
(如果是 IDE
的硬盤,那么對應(yīng)的設(shè)備就是 /dev/hda
啦)設(shè)備中讀出硬盤的信息,例如:
用 dd
命令復(fù)制出硬盤的前 512 個字節(jié),要 Root 用戶
$ sudo dd if=/dev/sda of=mbr.bin bs=512 count=1
用 file
命令查看相應(yīng)的信息
$ file mbr.bin
mbr.bin: x86 boot sector, LInux i386 boot LOader; partition 3: ID=0x82, starthead 254, startsector 19535040, 1959930 sectors; partition 4: ID=0x5, starthead 254, startsector 21494970, 56661255 sectors, code offset 0x48
也可以用 od
命令以 16 進制的形式讀取并進行分析
$ od -x mbr.bin
bs
是塊的大?。ㄒ宰止?jié) bytes
為單位),count
是塊數(shù)
因為這些信息并不直觀(而且下面會進一步深入分析),那么先來看看另外一個設(shè)備文件,將可以非常直觀地演示設(shè)備文件和硬件的對應(yīng)關(guān)系。還是以鼠標為例吧,下面來讀取鼠標對應(yīng)的設(shè)備文件的信息。
$ sudo -s
# cat /dev/input/mouse1 | od -x
你的鼠標驅(qū)動可能不太一樣,所以設(shè)備文件可能是其他的,但是都會在 /dev/input
下。
移動鼠標看看,是不是發(fā)現(xiàn)有不同信息輸出?;谶@一原理,我們經(jīng)常通過在一端讀取設(shè)備文件 /dev/ttyS0
中的內(nèi)容,而在另一端往設(shè)備文件 /dev/ttyS0
中寫入內(nèi)容來檢查串口線是否被損壞。
到這里,對設(shè)備驅(qū)動、設(shè)備文件和硬件設(shè)備之間的關(guān)聯(lián)應(yīng)該是印象更深刻了。如果想深入了解設(shè)備驅(qū)動的工作原理和設(shè)備驅(qū)動的編寫,那么看看下面列出的相關(guān)資料,開始設(shè)備驅(qū)動的編寫歷程吧。
參考資料:
實際上內(nèi)存、u 盤等都可以作為文件系統(tǒng)底層的“存儲”設(shè)備,但是這里僅用硬盤作為實例來介紹磁盤和分區(qū)的關(guān)系。
目前 Linux 的分區(qū)依然采用第一臺PC硬盤所使用的分區(qū)原理,下面逐步分析和演示這一分區(qū)原理。
先來看看幾個概念:
設(shè)備管理和分區(qū)
Linux 下,每一個存儲設(shè)備對應(yīng)一個系統(tǒng)的設(shè)備文件,對于硬盤等 IDE
和 SCSI
設(shè)備,在系統(tǒng)的 /dev
目錄下可以找到對應(yīng)的包含字符 hd
和 sd
的設(shè)備文件。而根據(jù)硬盤連接的主板設(shè)備接口和數(shù)據(jù)線接口的不同,在 hd
或者 sd
字符后面可以添加一個從 a
到 z
的字符,例如 hda
,hdb
,hdc
和 sda
,sdb
,sdc
等,另外為了區(qū)別同一個硬件設(shè)備的不同分區(qū),在后面還可以添加了一個數(shù)字,例如 hda1
,hda2
,hda3
和 sda1
,sda2
,sda3
,所以在 /dev
目錄下,可以看到很多類似的設(shè)備文件。
各分區(qū)的作用
在分區(qū)時常遇到主分區(qū)和邏輯分區(qū)的問題,這實際上是為了方便擴展分區(qū),正如后面的邏輯卷的引入是為了更好地管理多個硬盤一樣,引入主分區(qū)和邏輯分區(qū)可以方便地進行分區(qū)的管理。
Linux 系統(tǒng)中每一個硬盤設(shè)備最多由 4 個主分區(qū)(包括擴展分區(qū))構(gòu)成。
主分區(qū)的作用是計算機用來進行啟動操作系統(tǒng)的,因此每一個操作系統(tǒng)的啟動程序或者稱作是引導(dǎo)程序,都應(yīng)該存放在主分區(qū)上。 Linux 規(guī)定主分區(qū)(或者擴展分區(qū))占用分區(qū)編號中的前 4 個。所以會看到主分區(qū)對應(yīng)的設(shè)備文件為 /dev/hda1-4
或者 /dev/sda1-4
,而不會是 hda5
或者 sda5
。
擴展分區(qū)則是為了擴展更多的邏輯分區(qū)的,在 Linux 下,邏輯分區(qū)占用了 hda5-16
或者 sda5-16
等 12 個編號。
它規(guī)定了這個分區(qū)上的文件系統(tǒng)的類型。Linux支持諸如msdoc,vfat,ext2,ext3等諸多的文件系統(tǒng)類型,更多信息在下一小節(jié)進行進一步的介紹。
下面通過分析硬盤的前 512 個字節(jié)(即 MBR
)來分析和理解分區(qū)。
先來看看這張圖:
它用來描述 MBR
的結(jié)構(gòu)。 MBR
包括引導(dǎo)部分、分區(qū)表、以及結(jié)束標記 `(55AAH),分別占用了 512 字節(jié)中 446 字節(jié)、 64 字節(jié)和 2 字節(jié)。這里僅僅關(guān)注分區(qū)表部分,即中間的 64 字節(jié)以及圖中左邊的部分。
由于我用的是 SCSI
的硬盤,下面從 /dev/sda
設(shè)備中把硬盤的前 512 個字節(jié)拷貝到文件 mbr.bin
中。
$ sudo -s
# dd if=/dev/sda of=mbr.bin bs=512 count=1
下面用 file
,od
,fdisk
等命令來分析這段 MBR
的數(shù)據(jù),并對照上圖以便加深理解。
$ file mbr.bin
mbr.bin: x86 boot sector, LInux i386 boot LOader; partition 3: ID=0x82, starthead 254, startsector 19535040, 1959930 sectors; partition 4: ID=0x5, starthead 254, startsector 21494970, 56661255 sectors, code offset 0x48
$ od -x mbr.bin | tail -6 #僅關(guān)注中間的64字節(jié),所以截取了結(jié)果中后6行
0000660 0000 0000 0000 0000 a666 a666 0000 0180
0000700 0001 fe83 ffff 003f 0000 1481 012a 0000
0000720 0000 0000 0000 0000 0000 0000 0000 fe00
0000740 ffff fe82 ffff 14c0 012a e7fa 001d fe00
0000760 ffff fe05 ffff fcba 0147 9507 0360 aa55
$ sudo -s
# fdisk -l | grep ^/ #僅分析MBR相關(guān)的部分,不分析邏輯分區(qū)部分
/dev/sda1 * 1 1216 9767488+ 83 Linux
/dev/sda3 1217 1338 979965 82 Linux swap / Solaris
/dev/sda4 1339 4865 28330627+ 5 Extended
file
命令的結(jié)果顯示,剛拷貝的 512 字節(jié)是啟動扇區(qū),用分號分開的幾個部分分別是 bootloader
,分區(qū) 3 和分區(qū) 4 。分區(qū) 3 的類型是 82,即 swap
分區(qū)(可以通過 fdisk
命令的 l
命令列出相關(guān)信息),它對應(yīng) fdisk
的結(jié)果中 /dev/sda3
所在行的第 5 列,分區(qū) 3 的扇區(qū)數(shù)是 1959930,轉(zhuǎn)換成字節(jié)數(shù)是 1959930\*512
(目前,硬盤的默認扇區(qū)大小是 512 字節(jié)),而 swap
分區(qū)的默認塊大小是 1024 字節(jié),這樣塊數(shù)就是 :
$ echo 1959930*512/1024 | bc
979965
正好是 fdisk
結(jié)果中 /dev/sda3
所在行的第四列對應(yīng)的塊數(shù),同樣地,可以對照 fdisk
和 file
的結(jié)果分析分區(qū) 4 。
再來看看 od
命令以十六進制顯示的結(jié)果,同樣考慮分區(qū) 3,計算一下發(fā)現(xiàn),分區(qū) 3 對應(yīng)的 od
命令的結(jié)果為:
fe00 ffff fe82 ffff 14c0 012a e7fa 001d
首先是分區(qū)標記,00H
,從上圖中,看出它就不是引導(dǎo)分區(qū)(80H
標記的才是引導(dǎo)分區(qū)),而分區(qū)類型呢?為 82H
,和 file
顯示結(jié)果一致,現(xiàn)在再來關(guān)注一下分區(qū)大小,即 file
結(jié)果中的扇區(qū)數(shù)。
$ echo "ibase=10;obase=16;1959930" | bc
1DE7FA
剛好對應(yīng) e7fa 001d
,同樣地考慮引導(dǎo)分區(qū)的結(jié)果:
0180 0001 fe83 ffff 003f 0000 1481 012a
分區(qū)標記: 80H
,正好反應(yīng)了這個分區(qū)是引導(dǎo)分區(qū),隨后是引導(dǎo)分區(qū)所在的磁盤扇區(qū)情況,010100,即 1 面 0 道 1 扇區(qū)。其他內(nèi)容可以對照分析。
考慮到時間關(guān)系,更多細節(jié)請參考下面的資料或者查看看系統(tǒng)的相關(guān)手冊。
補充:安裝系統(tǒng)時,可以用 fdisk
,cfdisk
等命令進行分區(qū)。如果要想從某個分區(qū)啟動,那么需要打上 80H
標記,例如可通過 cfdisk
把某個分區(qū)設(shè)置為 bootable
來實現(xiàn)。
參考資料:
在沒有引入邏輯卷之前,分區(qū)類型和文件系統(tǒng)類型幾乎可以同等對待,設(shè)置分區(qū)類型的過程就是格式化分區(qū),建立相應(yīng)的文件系統(tǒng)類型的過程。
下面主要介紹如何建立分區(qū)和文件系統(tǒng)類型的聯(lián)系,即如何格式化分區(qū)為指定的文件系統(tǒng)類型。
先來看看 Linux 下文件系統(tǒng)的常見類型(如果要查看所有 Linux 支持的文件類型,可以用 fdisk
命令的 l
命令查看,或者通過 man fs
查看,也可通過 /proc/filesystems
查看到當前內(nèi)核支持的文件系統(tǒng)類型)
ext2
,ext3
,ext4
:這三個是 Linux 根文件系統(tǒng)通常采用的類型swap
:這個是實現(xiàn) Linux 虛擬內(nèi)存時采用的一種文件系統(tǒng),安裝時一般需要建立一個專門的分區(qū),并格式化為 swap
文件系統(tǒng)(如果想添加更多 swap
分區(qū),可以參考本節(jié)的參考資料,熟悉 dd
,mkswap
,swapon
,swapoff
等命令的用法)proc
:這是一種比較特別的文件系統(tǒng),作為內(nèi)核和用戶之間的一個接口存在,建立在內(nèi)存中(可以通過 cat
命令查看 /proc
系統(tǒng)下的文件,甚至可以通過修改 /proc/sys
下的文件實時調(diào)整內(nèi)核配置,當前前提是需要把 proc
文件系統(tǒng)掛載上: mount -t proc proc /proc
除了上述文件系統(tǒng)類型外,Linux 支持包括 vfat
,iso
,xfs
,nfs
在內(nèi)各種常見的文件系統(tǒng)類型,在 Linux 下,可以自由地查看和操作 Windows 等其他操作系統(tǒng)使用的文件系統(tǒng)。
那么如何建立磁盤和這些文件系統(tǒng)類型的關(guān)聯(lián)呢?格式化。
格式化的過程實際上就是重新組織分區(qū)的過程,可通過 mkfs
命令來實現(xiàn),當然也可以通過 fdisk
等命令來實現(xiàn)。這里僅介紹 mkfs
,mkfs
可用來對一個已有的分區(qū)進行格式化,不能實現(xiàn)分區(qū)操作(如果要對一個磁盤進行分區(qū)和格式化,那么可以用 fdisk
)。格式化后,相應(yīng)分區(qū)上的數(shù)據(jù)就會通過某種特別的文件系統(tǒng)類型進行組織。
例如:把 /dev/sda9
分區(qū)格式化為 ext3
的文件系統(tǒng)。
$ sudo -s
# mkfs -t ext3 /dev/sda9
如果要列出各個分區(qū)的文件系統(tǒng)類型,那么可以用 fdisk -l
命令。
更多信息請參考下列資料。
參考資料:
上一節(jié)直接把分區(qū)格式化為某種文件系統(tǒng)類型,但是考慮到擴展新的存儲設(shè)備的需要,開發(fā)人員在文件系統(tǒng)和分區(qū)之間引入了邏輯卷??紤]到時間關(guān)系,這里不再詳述,請參考資料:Linux 邏輯卷管理詳解
文件系統(tǒng)最終呈現(xiàn)出來的是一種可視化的結(jié)構(gòu),可用ls,find,tree等命令把它呈現(xiàn)出來。它就像一顆倒掛的“樹”,在樹的節(jié)點上還可以掛載新的“樹”。
下面簡單介紹文件系統(tǒng)的掛載。
一個文件系統(tǒng)可以通過一個設(shè)備掛載(mount
)到某個目錄下,這個目錄被稱為掛載點。有趣的是,在 Linux 下,一個目錄本身還可以掛載到另外一個目錄下,一個格式化了的文件也可以通過一個特殊的設(shè)備 /dev/loop
進行掛載(如 iso
文件)。另外,就文件系統(tǒng)而言,Linux 不僅支持本地文件系統(tǒng),還支持遠程文件系統(tǒng)(如 nfs
)。
下面簡單介紹文件系統(tǒng)掛載的幾個實例。
掛載需要 Root 權(quán)限,例如,掛載系統(tǒng)根文件系統(tǒng) /dev/sda1
到 /mnt
$ sudo -s
# mount -t ext3 /dev/sda1 /mnt/
查看 /dev/sda1
的掛載情況,可以看到,一個設(shè)備可以多次掛載
$ mount | grep sda1
/dev/sda1 on / type ext3 (rw,errors=remount-ro)
/dev/sda1 on /mnt type ext3 (rw)
對于一個已經(jīng)掛載的文件系統(tǒng),為支持不同屬性可以重新掛載
$ mount -n -o remount, rw /
如果內(nèi)核已經(jīng)支持 USB 接口,那么插入 u 盤時,可以通過 dmesg
命令查看對應(yīng)的設(shè)備號,并掛載它。
查看 dmesg
結(jié)果中的最后幾行內(nèi)容,找到類似 /dev/sdN
的信息,找出 u 盤對應(yīng)的設(shè)備號
$ dmesg
這里假設(shè) u 盤是 vfat
格式,以便在一些打印店里的 Windows 上也可使用
# mount -t vfat /dev/sdN /path/to/mountpoint_directory
對于一些iso文件或者是 iso 格式的光盤,同樣可以通過 mount
命令掛載。
對于 iso 文件:
# mount -t iso9660 /path/to/isofile /path/to/mountpoint_directory
對于光盤:
# mount -t iso9660 /dev/cdrom /path/to/mountpoint_directory
# mount -t nfs remote_ip:/path/to/share_directory /path/to/local_directory
# mount -t proc proc /proc
proc
文件系統(tǒng)組織在內(nèi)存中,但是可以把它掛載到某個目錄下。通常把它掛載在 /proc
目錄下,以便一些系統(tǒng)管理和配置工具使用它。例如 top
命令用它分析內(nèi)存的使用情況(讀取 /proc/meminfo
和 /proc/stat
等文件中的內(nèi)容); lsmod
命令通過它獲取內(nèi)核模塊的狀態(tài)(讀取 /proc/modules
); netstat
命令通過它獲取網(wǎng)絡(luò)的狀態(tài)(讀取 /proc/net/dev
等文件)。當然,也可以編寫相關(guān)工具。除此之外,通過調(diào)整 /proc/sys
目錄下的文件,可以動態(tài)地調(diào)整系統(tǒng)配置,比如往 /proc/sys/net/ipv4/ip_forward
文件中寫入數(shù)字 1 就可以讓內(nèi)核支持數(shù)據(jù)包轉(zhuǎn)發(fā)。(更多信息請參考 proc
的幫助,man``proc
)
$ mount --bind /path/to/needtomount_directory /path/to/mountpoint_directory
這個非常有意思,比如可以把某個目錄掛載到 ftp 服務(wù)的根目錄下,而無須把內(nèi)容復(fù)制過去,就可以把相應(yīng)目錄中的資源提供給別人共享。
以上都只提到了掛載,那怎么卸載呢?用 umount
命令跟上掛載的源地址或者掛載點(設(shè)備,文件,遠程目錄等)就可以。例如:
$ umount /path/to/mountpoint_directory
或者
$ umount /path/to/mount_source
如果想管理大量的或者經(jīng)常性的掛載服務(wù),那么每次手動掛載是很糟糕的事情。這時就可利用 mount
的配置文件 /etc/fstab
,把 mount
對應(yīng)的參數(shù)寫到 /etc/fstab
文件對應(yīng)的列中即可實現(xiàn)批量掛載( mount -a
)和卸載( umount -a
)。 /etc/fstab
中各列分別為文件系統(tǒng)、掛載點、類型、相關(guān)選項。更多信息可參考 fstab
的幫助( man fstab
)。
參考資料:
Linux 文件系統(tǒng)下有一些最基本的目錄,不同的目錄下存放著不同作用的各類文件。最基本的目錄有 /etc
,/lib
,/dev
,/bin
等,它們分別存放著系統(tǒng)配置文件,庫文件,設(shè)備文件和可執(zhí)行程序。這些目錄一般情況下是必須的,在做嵌入式開發(fā)時,需要手動或者是用 busybox
等工具來創(chuàng)建這樣一個基本的文件系統(tǒng)。這里僅制作一個非常簡單的文件系統(tǒng),并對該文件系統(tǒng)進行各種常規(guī)操作,以便加深對文件系統(tǒng)的理解。
還記得 dd
命令么?就用它來產(chǎn)生一個固定大小的文件,這個為 1M(1024\*1024 bytes)
的文件
$ dd if=/dev/zero of=minifs bs=1024 count=1024
查看文件類型,這里的 minifs
是一個充滿 \\0
的文件,沒有任何特定的數(shù)據(jù)結(jié)構(gòu)
$ file minifs
minifs: data
說明: /dev/zero
是一個非常特殊的設(shè)備,如果讀取它,可以獲取任意多個 \\0
。
接著把該文件格式化為某個指定文件類型的文件系統(tǒng)。(是不是覺得不可思議,文件也可以格式化?是的,不光是設(shè)備可以,文件也可以以某種文件系統(tǒng)類型進行組織,但是需要注意的是,某些文件系統(tǒng)(如 ext3
)要求被格式化的目標最少有 64M
的空間)。
$ mkfs.ext2 minifs
查看此時的文件類型,這時文件 minifs
就以 ext2
文件系統(tǒng)的格式組織了
$ file minifs
minifs: Linux rev 1.0 ext2 filesystem data
因為該文件以文件系統(tǒng)的類型組織了,那么可以用 mount
命令掛載并使用它。
請切換到 root
用戶掛載它,并通過 -o loop
選項把它關(guān)聯(lián)到一個特殊設(shè)備 /dev/loop
$ sudo -s
# mount minifs /mnt/ -o loop
查看該文件系統(tǒng)信息,僅可以看到一個目錄文件 lost+found
$ ls /mnt/
lost+found
在該文件系統(tǒng)下進行各種常規(guī)操作,包括讀、寫、刪除等。(每次操作前先把 minifs
文件保存一份,以便比較,結(jié)合相關(guān)資料就可以深入地分析各種操作對文件系統(tǒng)的改變情況,從而深入理解文件系統(tǒng)作為一種組織數(shù)據(jù)的方式的實現(xiàn)原理等)
$ cp minifs minifs.bak
$ cd /mnt
$ touch hello
$ cd -
$ cp minifs minifs-touch.bak
$ od -x minifs.bak > orig.od
$ od -x minifs-touch.bak > touch.od
創(chuàng)建一個文件后,比較此時文件系統(tǒng)和之前文件系統(tǒng)的異同
$ diff orig.od touch.od
diff orig.od touch.od
61,63c61,64
< 0060020 000c 0202 2e2e 0000 000b 0000 03e8 020a
< 0060040 6f6c 7473 662b 756f 646e 0000 0000 0000
< 0060060 0000 0000 0000 0000 0000 0000 0000 0000
---
> 0060020 000c 0202 2e2e 0000 000b 0000 0014 020a
> 0060040 6f6c 7473 662b 756f 646e 0000 000c 0000
> 0060060 03d4 0105 6568 6c6c 006f 0000 0000 0000
> 0060100 0000 0000 0000 0000 0000 0000 0000 0000
通過比較發(fā)現(xiàn):添加文件,文件系統(tǒng)的相應(yīng)位置發(fā)生了明顯的變化
$ echo "hello, world" > /mnt/hello
執(zhí)行 sync
命令,確保緩存中的數(shù)據(jù)已經(jīng)寫入磁盤(還記得本節(jié)圖 1 的 buffer cache
吧,這里就是把 cache
中的數(shù)據(jù)寫到磁盤中)
$ sync
$ cp minifs minifs-echo.bak
$ od -x minifs-echo.bak > echo.od
寫入文件內(nèi)容后,比較文件系統(tǒng)和之前的異同
$ diff touch.od echo.od
查看文件系統(tǒng)中的字符串
$ strings minifs
lost+found
hello
hello, world
刪除 hello
文件,查看文件系統(tǒng)變化
$ rm /mnt/hello
$ cp minifs minifs-rm.bak
$ od -x minifs-rm.bak > rm.od
$ diff echo.od rm.od
通過查看文件系統(tǒng)的字符串發(fā)現(xiàn):刪除文件時并沒有覆蓋文件內(nèi)容,所以從理論上說內(nèi)容此時還是可恢復(fù)的
$ strings minifs
lost+found
hello
hello, world
上面僅僅演示了一些分析文件系統(tǒng)的常用工具,并分析了幾個常規(guī)的操作,如果想非常深入地理解文件系統(tǒng)的實現(xiàn)原理,請熟悉使用上述工具并閱讀相關(guān)資料。
參考資料:
隨著 fuse
的出現(xiàn),在用戶空間開發(fā)文件系統(tǒng)成為可能,如果想開發(fā)自己的文件系統(tǒng),那么推薦閱讀:使用 fuse 開發(fā)自己的文件系統(tǒng)。
更多建議: