描述: 圖[1] Filesystem Structure
圖片:

描述: 圖[2] MBR Structure
圖片:
by falcon<zhangjinw@gmail.com>
2007-12-20
前言
準(zhǔn)備了很久,找了好多天的資料,還不知道應(yīng)該如何開始動(dòng)筆寫:因?yàn)閾?dān)心“拿捏”不住,所以一方面繼續(xù)查找資料,一方面思考如何來寫。作為“shell編程
范例”序列的一部分,希望它能夠很好地幫助shell程序員理解如何用shell命令來完成和Linux系統(tǒng)關(guān)系非常之大的文件系統(tǒng)的各種操作,希望讓
Shell程序員中對(duì)文件系統(tǒng)"混沌"的狀態(tài)從此消失,希望文件系統(tǒng)以一種更為清晰的樣子呈現(xiàn)在我們的眼前。
正文
-1 文件系統(tǒng)在Linux操作系統(tǒng)中的位置
如何來認(rèn)識(shí)文件系統(tǒng)呢?從shell程序員的角度來看,文件系統(tǒng)就是一個(gè)用來組織各種文件的方法。但是文件系統(tǒng)無法獨(dú)立于硬件存儲(chǔ)設(shè)備和操作系統(tǒng)而獨(dú)立存
在,因此我們還是有必要來弄清楚硬件存儲(chǔ)設(shè)備、分區(qū)、操作系統(tǒng)、邏輯卷、文件系統(tǒng)等各種概念之間的聯(lián)系,以便理解我們對(duì)文件系統(tǒng)的常規(guī)操作的一些“細(xì)
節(jié)”。這個(gè)聯(lián)系或許(也許會(huì)有一些問題)可以通過這樣一種方式來呈現(xiàn),如附錄圖[1]。
從該圖中,我們可以清晰地看到各個(gè)“概念”之間的關(guān)系,它們以不同層次分布,覆蓋硬件設(shè)備、系統(tǒng)內(nèi)核空間、系統(tǒng)用戶空間。在用戶空間,用戶可以不管內(nèi)核是
如何操作具體硬件設(shè)備的,僅僅使用程序員設(shè)計(jì)的各種界面就可以拉,而普通程序員也僅僅需要利用內(nèi)核提供的各種接口(system
call)或者一些C庫(kù)來和內(nèi)核進(jìn)行交互,而無須關(guān)心具體的實(shí)現(xiàn)細(xì)節(jié)。不過對(duì)于操作系統(tǒng)開發(fā)人員,他們需要在內(nèi)核空間設(shè)計(jì)特定的數(shù)據(jù)結(jié)構(gòu)來管理和組織底層
的硬件設(shè)備。
下面我們從下到上的方式(即從底層硬件開始),用工具來分析和理解圖中幾個(gè)重要的概念。(如果有興趣,可以先看看下面的幾則資料)
參考資料:
[1] Linux 系統(tǒng)的基本組成和文件系統(tǒng)結(jié)構(gòu)
http://forum.ubuntu.org.cn/weblog_entry.php?e=332&sid=3ceee92718a77d5eef867497470ecc7b
[2] 從文件 I/O 看 Linux 的虛擬文件系統(tǒng)
http://www.ibm.com/developerworks/cn/linux/l-cn-vfs/
[3] Linux 文件系統(tǒng)剖析 http://www.ibm.com/developerworks/cn/linux/l-linux-filesystem/index.html?ca=drs-cn
[4] 第九章 文件系統(tǒng)
http://man.chinaunix.net/tech/lyceum/linuxK/fs/filesystem.html
[5] Linux邏輯盤卷管理LVM詳解
http://unix-cd.com/vc/www/28/2007-06/1178.html
0 硬件管理和設(shè)備驅(qū)動(dòng)
Linux系統(tǒng)通過不同的設(shè)備驅(qū)動(dòng)模塊管理不同的硬件設(shè)備。如果添加了新的硬件設(shè)備,那么需要編寫相應(yīng)的硬件驅(qū)動(dòng)模塊來管理它。對(duì)于一些常見的硬件設(shè)備,
系統(tǒng)已經(jīng)自帶了相應(yīng)的驅(qū)動(dòng),編譯內(nèi)核時(shí),選中它們,可以把它們編譯成內(nèi)核的一部分,也可以以模塊的方式編譯。如果以模塊的方式編譯,那么可以在系統(tǒng)的
/lib/modules/`uname -r`目錄下找到對(duì)應(yīng)的模塊文件。
比如,可以這樣找到相應(yīng)的scsi驅(qū)動(dòng)和usb驅(qū)動(dòng)的模塊:
| Quote: |
|
// 更新系統(tǒng)中文件索引數(shù)據(jù)庫(kù)(有點(diǎn)慢,不耐煩就按下CTRL+C取消掉) $ updatedb // 查找scsi相關(guān)的驅(qū)動(dòng) $ locate scsi*.ko // 查找usb相關(guān)的驅(qū)動(dòng) $ locate usb*.ko
|
這些驅(qū)動(dòng)的名字以.ko為后綴,在安裝系統(tǒng)時(shí)默認(rèn)編譯為了模塊。實(shí)際上可以把它們編譯為內(nèi)核的一部分,僅僅需要在編譯內(nèi)核時(shí)選擇為
即可(更多內(nèi)核模塊編譯的資料請(qǐng)參考資料[5])。但是,很多情況下會(huì)以模塊的方式編譯它們,這樣可以減少內(nèi)核的大小,并根據(jù)需要靈活地加載和卸載它們。下面簡(jiǎn)單地演示如何查看已加載模塊的狀態(tài),卸載模塊,加載模塊。
可通過查看/proc文件系統(tǒng)的modules文件檢查內(nèi)核中已加載的各個(gè)模塊的狀態(tài),也可以通過lsmod命令直接查看它們。
| Quote: |
|
$ cat /proc/modules 或者 $ lsmod // 例如,查看scsi和usb相關(guān)驅(qū)動(dòng)模塊如下,結(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ū)動(dòng)哦!因?yàn)槟愕南到y(tǒng)就跑在上面,如果確實(shí)想玩玩,卸載前記得保存數(shù)據(jù)),通過rmmod命令就可以實(shí)現(xiàn)。
| Quote: |
|
// 先切換到root用戶 $ rmmod usbhid // 再查看該模塊的信息,已經(jīng)看不到了吧 $ lsmod | grep ^usbhid
|
如果你有個(gè)usb鼠標(biāo),那么移動(dòng)一下,是不是發(fā)現(xiàn)動(dòng)不了啦?因?yàn)樵O(shè)備驅(qū)動(dòng)都沒有了,設(shè)備自然就沒法用羅。不過不要緊張,既然知道是什么原因,那么把設(shè)備驅(qū)動(dòng)重新加載上就可以啦,下面用insmod把usbhid模塊重新加載上。
| Quote: |
|
// 也要root用戶的 $ insmod `locate usbhid.ko` // `locate usbhid.ko`是為了找出usbhid.ko模塊的路徑,如果你之前沒有updatedb,估計(jì)用它是找不到了,不過你可以直接到/lib/modules目錄下把usbhid.ko文件找到。
|
okay,現(xiàn)在鼠標(biāo)又可以用啦,不信再動(dòng)一下鼠標(biāo) :-)
到這里,硬件設(shè)備和設(shè)備驅(qū)動(dòng)之間關(guān)系應(yīng)該是比較清楚了吧。如果沒有,那么繼續(xù)下面的內(nèi)容。
在Linux下,設(shè)備驅(qū)動(dòng)關(guān)聯(lián)著相應(yīng)的設(shè)備文件,而設(shè)備文件則和硬件設(shè)備一一對(duì)應(yīng)(更多細(xì)節(jié)請(qǐng)參考資料[8][9][10])。這些設(shè)備文件都統(tǒng)一存放在系統(tǒng)的/dev/目錄下。
例如,scsi設(shè)備對(duì)應(yīng)的/dev/sda,/dev/sda1,/dev/sda2...下面查看這些設(shè)備文件的信息。
| Quote: |
|
$ 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
|
可以看到第一列第一個(gè)字符都是b,第五列都是數(shù)字8。b表示該文件是一個(gè)塊設(shè)備文件,對(duì)應(yīng)地,如果是c則表示字符設(shè)備(例如/dev/ttyS0,關(guān)于塊設(shè)備和字符設(shè)備的區(qū)別,可以看這里[摘自網(wǎng)絡(luò)])。
| Quote: |
|
字符設(shè)備:字符設(shè)備就是能夠像字節(jié)流一樣訪問的設(shè)備,字符終端和串口就屬于字符設(shè)備。
塊設(shè)備:塊設(shè)備上可以容納文件系統(tǒng)。與字符設(shè)備不同,在讀寫操作時(shí),塊設(shè)備每次只能傳輸一個(gè)或多個(gè)完整的塊。在Linux操作系統(tǒng)中,應(yīng)用程序可以像訪問
字符設(shè)備一樣讀寫塊設(shè)備(一次讀取或?qū)懭肴我獾淖止?jié)數(shù)據(jù))。因此,塊設(shè)備和字符設(shè)備的區(qū)別僅僅是在內(nèi)核中對(duì)于數(shù)據(jù)的管理不同。
|
數(shù)字8則是該硬件設(shè)備在內(nèi)核中對(duì)應(yīng)的設(shè)備編號(hào),可以在內(nèi)核的Documentation/devices.txt文件中找到設(shè)備號(hào)分配情況。但是為什么同
一個(gè)設(shè)備會(huì)對(duì)應(yīng)不同的設(shè)備文件(/dev/sda后面為什么還有不同的數(shù)字,而且ls結(jié)果中的第6列貌似和它們對(duì)應(yīng)起來的)。這實(shí)際上是為了區(qū)分不同設(shè)備
的不同部分。對(duì)于硬盤,這樣可以處理硬盤內(nèi)部的不同分區(qū)。就內(nèi)核而言,它僅僅需要通過第5列的設(shè)備號(hào)就可以找到對(duì)應(yīng)的硬件設(shè)備,但是對(duì)于驅(qū)動(dòng)模塊來說,它
還需要知道如何處理不同的分區(qū),于是就多了一個(gè)輔設(shè)備號(hào),即第6列對(duì)應(yīng)的內(nèi)容。這樣一個(gè)設(shè)備就有了主設(shè)備號(hào)(第5列)和輔設(shè)備號(hào)(第6列),從而方便的實(shí)
現(xiàn)對(duì)各種硬件設(shè)備的管理。
因?yàn)樵O(shè)備文件和硬件是對(duì)應(yīng)的,這樣我們可以直接從/dev/sda(如果是IDE的硬盤,那么對(duì)應(yīng)的設(shè)備就是/dev/hda啦)設(shè)備中讀出硬盤的信息,例如:
| Quote: |
|
// 用dd命令復(fù)制出硬盤的前512個(gè)字節(jié),要root用戶哦 $ 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進(jìn)制的形式讀取并進(jìn)行分析 $ od -x mbr.bin // bs是塊的大小(以字節(jié)bytes為單位),count是塊數(shù)
|
因?yàn)檫@些信息并不是很直觀(而且下面我們會(huì)進(jìn)一步深入的分析),那么我們來看看另外一個(gè)設(shè)備文件,將可以非常直觀的演示設(shè)備文件和硬件的對(duì)應(yīng)關(guān)系。還是以鼠標(biāo)為例吧,下面來讀取鼠標(biāo)對(duì)應(yīng)的設(shè)備文件的信息。
| Quote: |
|
// 同樣需要root用戶 $ cat /dev/input/mouse1 | od -x // 你的鼠標(biāo)驅(qū)動(dòng)可能不太一樣,所以設(shè)備文件可能是其他的,但是都會(huì)在/dev/input下
|
移動(dòng)鼠標(biāo)看看,是不是發(fā)現(xiàn)有不同信息輸出。(基于這一原理,我們經(jīng)常通過在一端讀取設(shè)備文件/dev/ttyS0中的內(nèi)容,而在另一端往設(shè)備文件/dev/ttyS0中寫入內(nèi)容來檢查串口線是否被損壞。)
到這里,對(duì)設(shè)備驅(qū)動(dòng)、設(shè)備文件和硬件設(shè)備之間的關(guān)聯(lián)應(yīng)該是印象更深刻了。如果想深入了解設(shè)備驅(qū)動(dòng)的工作原理和設(shè)備驅(qū)動(dòng)模塊的編寫,那么看看參考資料[10],開始你的設(shè)備驅(qū)動(dòng)模塊的編寫歷程吧。
參考資料:
[5] Compile linux kernel 2.6
http://www.cyberciti.biz/tips/compiling-linux-kernel-26.html
[6] Linux系統(tǒng)的硬件驅(qū)動(dòng)程序編寫原理
http://www.blue1000.com/bkhtml/2001-02/2409.htm
[7] Linux下USB設(shè)備的原理、配置、 常見問題
http://soft.zdnet.com.cn/software_zone/2007/1108/617545.shtml
[8] Linux 核心--9.設(shè)備驅(qū)動(dòng)
http://www.bitscn.com/linux/driver/200604/6788.html
[9] The Linux Kernel Module Programming Guide
http://www.dirac.org/linux/writing/lkmpg/2.6/lkmpg-2.6.0.html
[10] Linux設(shè)備驅(qū)動(dòng)開發(fā)
http://linuxdriver.co.il/ldd3/
1 理解、查看磁盤分區(qū)
實(shí)際上內(nèi)存、u盤等都可以作為文件系統(tǒng)底層的“存儲(chǔ)”設(shè)備,但是這里我們僅用硬盤作為實(shí)例來介紹磁盤和分區(qū)的關(guān)系。
目前Linux的分區(qū)依然采用第一臺(tái)PC硬盤所使用的分區(qū)原理(見該部分的參考資料[1]),下面逐步分析和演示這一分區(qū)原理。
先來看看幾個(gè)概念:
A. 設(shè)備管理和分區(qū)
在Linux下,每一個(gè)存儲(chǔ)設(shè)備對(duì)應(yīng)一個(gè)系統(tǒng)的設(shè)備文件,對(duì)于硬盤等IDE和SCSI設(shè)備,在系統(tǒng)的/dev目錄下可以找到對(duì)應(yīng)的包含字符hd和sd的設(shè)
備文件。而根據(jù)硬盤連接的主板設(shè)備接口和數(shù)據(jù)線接口的不同,在hd或者sd字符后面可以添加一個(gè)從a到z的字符,例如hda,hdb,hdc和sda,
sdb,sdc等,另外為了區(qū)別同一個(gè)硬件設(shè)備的不同分區(qū),在后面還可以添加了一個(gè)數(shù)字,例如hda1,hda2,hda3...和sda1,sda2,
sda3,所以你在/dev目錄下,可以看到很多類似的設(shè)備文件。
B. 各分區(qū)的作用
在分區(qū)的時(shí)候常遇到主分區(qū)和邏輯分區(qū)的問題,這實(shí)際上是為了方便擴(kuò)展分區(qū),正如后面的邏輯卷的引入是為了更好地管理多個(gè)硬盤一樣,引入主分區(qū)和邏輯分區(qū)可以方便地進(jìn)行分區(qū)的管理。
在Linux系統(tǒng)中,每一個(gè)硬盤設(shè)備最多由4個(gè)主分區(qū)(包括擴(kuò)展分區(qū))構(gòu)成。
主分區(qū)的作用是計(jì)算機(jī)用來進(jìn)行啟動(dòng)操作系統(tǒng)的,因此每一個(gè)操作系統(tǒng)的啟動(dòng)程序或者稱作是引導(dǎo)程序,都應(yīng)該存放在主分區(qū)上。Linux規(guī)定主分區(qū)(或者擴(kuò)展
分區(qū))占用分區(qū)編號(hào)中的前4個(gè)。所以你會(huì)看到主分區(qū)對(duì)應(yīng)的設(shè)備文件為/dev/hda1-4或者/dev/sda1-4,而不會(huì)是hda5或者sda5。
擴(kuò)展分區(qū)則是為了擴(kuò)展更多的邏輯分區(qū)的,在Linux下,邏輯分區(qū)占用了hda5-16或者sda5-16等12個(gè)編號(hào)。
C. 分區(qū)類型
它規(guī)定了這個(gè)分區(qū)上的文件系統(tǒng)的類型。Linux支持諸如msdoc,vfat,ext2,ext3等諸多的文件系統(tǒng)類型,更多信息在下一小節(jié)進(jìn)行進(jìn)一步的介紹。
下面通過分析硬盤的前512個(gè)字節(jié)(即MBR)來分析和理解分區(qū)。
先來看看這張表(見附圖2),它用來描述MBR的結(jié)構(gòu)。MBR包括引導(dǎo)部分、分區(qū)表、以及結(jié)束標(biāo)記(55AAH),分別占用了512字節(jié)中446字節(jié)、
64字節(jié)和2字節(jié)。這里僅僅關(guān)注分區(qū)表部分,即中間的64字節(jié)以及圖中左邊的部分。(如果你對(duì)引導(dǎo)部分感興趣,請(qǐng)參考資料[10][11][12])
由于我用的是SCSI的硬盤,下面從/dev/sda設(shè)備中把硬盤的前512個(gè)字節(jié)拷貝到文件mbr.bin中。
| Quote: |
|
// 先切換到root用戶 $ dd if=/dev/sda of=mbr.bin bs=512 count=1
|
下面用file,od,fdisk等命令來分析這段MBR的數(shù)據(jù),并對(duì)照附圖[2]以便加深理解。
| Quote: |
|
$ 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 // 先切換到root用戶 $ 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é)是啟動(dòng)扇區(qū),用分號(hào)分開的幾個(gè)部分分別是boot
loader,分區(qū)3和分區(qū)4。分區(qū)3的類型是82,即swap分區(qū)(可以通過fdisk命令的l命令列出相關(guān)信息),它對(duì)應(yīng)fdisk的結(jié)果中
/dev/sda3所在行的第5列,分區(qū)3的扇區(qū)數(shù)是1959930,轉(zhuǎn)換成字節(jié)數(shù)是1959930*512(目前,硬盤的默認(rèn)扇區(qū)大小是512字節(jié)),
而swap分區(qū)的默認(rèn)塊大小是1024字節(jié),這樣塊數(shù)就是:
| Quote: |
|
$ echo 1959930*512/1024 | bc 979965
|
正好是fdisk結(jié)果中/dev/sda3所在行的第四列對(duì)應(yīng)的塊數(shù),同樣地,可以對(duì)照fdisk和file的結(jié)果分析分區(qū)4。
再來看看od命令以十六進(jìn)制顯示的結(jié)果,同樣考慮分區(qū)3,計(jì)算一下發(fā)現(xiàn),分區(qū)3對(duì)應(yīng)的od命令的結(jié)果為:
| Quote: |
|
fe00 ffff fe82 ffff 14c0 012a e7fa 001d
|
首先是分區(qū)標(biāo)記,00H,從圖[2]中,看出它就不是引導(dǎo)分區(qū)(80H標(biāo)記的才是引導(dǎo)分區(qū)),而分區(qū)類型呢?為82H,和file顯示結(jié)果一致,現(xiàn)在再來關(guān)注一下分區(qū)大小,即file結(jié)果中的扇區(qū)數(shù)。
| Quote: |
|
$ echo "ibase=10;obase=16;1959930" | bc 1DE7FA
|
剛好對(duì)應(yīng)e7fa 001d,同樣地考慮引導(dǎo)分區(qū)的結(jié)果:
| Quote: |
|
0180 0001 fe83 ffff 003f 0000 1481 012a
|
分區(qū)標(biāo)記:80H,正好反應(yīng)了這個(gè)分區(qū)是引導(dǎo)分區(qū),隨后是引導(dǎo)分區(qū)所在的磁盤扇區(qū)情況,010100,即1面0道1扇區(qū)。其他內(nèi)容可以對(duì)照分析。
考慮到時(shí)間關(guān)系,更多細(xì)節(jié)請(qǐng)參考下面的資料或者查看看系統(tǒng)的相關(guān)手冊(cè)。
補(bǔ)充:安裝系統(tǒng)時(shí),可以用fdisk,cfdisk等命令進(jìn)行分區(qū)。如果要想從某個(gè)分區(qū)啟動(dòng),那么需要打上80H標(biāo)記,例如可通過cfdisk把某個(gè)分區(qū)設(shè)置為bootable來實(shí)現(xiàn)。
參考資料:
[1] 解析磁盤、分區(qū)、文件系統(tǒng)
http://www.linuxpk.com/37190.html
[2] 硬盤分區(qū)表詳解
http://www.linuxpk.com/5378.html
[3] 深入理解Linux的硬盤分區(qū)
http://www.linuxpk.com/39733.html
[4] 什么是硬件分區(qū)表
http://www.pc-web.cn/pc/basic/465.asp
[5] Linux指導(dǎo)第6部分 使用分區(qū)和文件系統(tǒng)
http://www.pass100.net/jisuanji/linux/zhidao/80974.html
[10] 硬盤MBR全面分析
http://www.pc120.net.cn/home/datcb/05101223070444577.htm
[11] Inside the linux boot process
http://www-128.ibm.com/developerworks/linux/library/l-linuxboot/
[12] Develop your own OS: booting
http://docs.huihoo.com/gnu_linux/own_os/booting.htm
[13] Redhat 9磁盤分區(qū)簡(jiǎn)介
http://www.topstudy.com/info/default.aspx?guid=eeac2894-3588-4b1a-9607-1ad377caa03f
[14] Linux partition HOWTO
http://mirror.lzu.edu.cn/tldp/HOWTO/Partition/
2 分區(qū)和文件系統(tǒng)的關(guān)系
在沒有引入邏輯卷之前,分區(qū)類型和文件系統(tǒng)類型幾乎可以同等對(duì)待,設(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查看到當(dāng)前內(nèi)核支持的文件系統(tǒng)類型)
ext2,ext3:這兩個(gè)是Linux根文件系統(tǒng)通常采用的類型
swap:這個(gè)是具體實(shí)現(xiàn)Linux虛擬內(nèi)存時(shí)采用的一種文件系統(tǒng),安裝時(shí)一般需要建立一個(gè)專門的分區(qū),并格式化為swap文件系統(tǒng)(如果想添加更多的
swap分區(qū),那么可以參考本節(jié)的資料[1],熟悉dd,mkswap,swapon,swapoff等命令的用法)
proc:這是一種比較特別的文件系統(tǒng),作為內(nèi)核和用戶之間的一個(gè)接口存在,建立在內(nèi)存中(你可以通過cat命令查看/proc系統(tǒng)下的文件,甚至可以通
過修改/proc/sys下的文件實(shí)時(shí)調(diào)整內(nèi)核的配置,當(dāng)前前提是你需要把proc文件系統(tǒng)掛載上[mount -t proc proc
/proc])
除了這三個(gè)最常見的文件系統(tǒng)類型外,Linux支持包括vfat,iso,xfs,nfs在內(nèi)各種常見的文件系統(tǒng)類型,在linux下,你可以自由地查看和操作windows等其他操作系統(tǒng)使用的文件系統(tǒng)。
那么如何建立磁盤和這些文件系統(tǒng)類型的關(guān)聯(lián)呢?格式化。
格式化的過程實(shí)際上就是重新組織分區(qū)的過程,可通過mkfs命令來實(shí)現(xiàn),當(dāng)然也可以通過fdisk等命令來實(shí)現(xiàn)。這里僅介紹mkfs,mkfs可用來對(duì)一
個(gè)已有的分區(qū)進(jìn)行格式化,不能實(shí)現(xiàn)分區(qū)操作(如果要對(duì)一個(gè)磁盤進(jìn)行分區(qū)和格式化,那么可以用fdisk就可以啦)。格式化后,相應(yīng)的分區(qū)上的數(shù)據(jù)就通過某
種特別的文件系統(tǒng)類型進(jìn)行組織了。
例如:把/dev/sda9分區(qū)格式化為ext3的文件系統(tǒng)。
| Quote: |
|
// 先切換到root用戶 $ mkfs -t ext3 /dev/sda9
|
如果要列出各個(gè)分區(qū)的文件系統(tǒng)類型,那么可以用fdisk -l命令。
更多信息請(qǐng)參考下列資料。
參考資料:
[1] Linux下加載swap分區(qū)的步驟
http://soft.zdnet.com.cn/software_zone/2007/1010/545261.shtml
[2] 光碟的標(biāo)準(zhǔn)
http://www.edisc.com.cn/bike/viewnews.btml?id=274
[3] Linux下ISO鏡像文件的制作與刻錄
http://www.examda.com/linux/fudao/20071212/113445321.html
[4] RAM磁盤分區(qū)解釋
http://oldlinux.org/oldlinux/viewthread.php?tid=2677
http://www.ibm.com/developerworks/cn/linux/l-initrd.html
[5] 高級(jí)文件系統(tǒng)實(shí)現(xiàn)者指南
http://www-128.ibm.com/developerworks/search/searchResults.jsp?searchType=1&searchSite=dWChina&pageLang=zh&langEncoding=UTF8&searchScope=dW&query=%E9%AB%98%E7%BA%A7%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E5%AE%9E%E7%8E%B0%E8%80%85%E6%8C%87%E5%8D%97&Search.x=42&Search.y=9&Search=%E6%90%9C%E7%B4%A2
(有必要突出解釋swap,RAM文件系統(tǒng)的工作原理等)
3 分區(qū)、邏輯卷和文件系統(tǒng)的關(guān)系
在上一節(jié)中,我們直接把分區(qū)格式化為某種文件系統(tǒng)類型,但是考慮到擴(kuò)展新的存儲(chǔ)設(shè)備的需要,開發(fā)人員在文件系統(tǒng)和分區(qū)之間引入了邏輯卷。考慮到時(shí)間關(guān)系,這里不再詳述,請(qǐng)參考資料[1]。
參考資料:
[1] Linux邏輯卷管理詳解
http://unix-cd.com/vc/www/28/2007-06/1178.html
[2] 見1.2的最后一個(gè)參考資料的最后一節(jié)
4 文件系統(tǒng)的可視化結(jié)構(gòu)
文件系統(tǒng)最終呈現(xiàn)出來的是一種可視化的結(jié)構(gòu),我們可用ls,find,tree等命令把它呈現(xiàn)出來。它就像一顆倒掛的“樹”,在樹的節(jié)點(diǎn)上還可以掛載新的“樹”。(如果想把目錄結(jié)構(gòu)以圖表的方式呈現(xiàn)出來,那么可以使用我之前寫的一個(gè)腳本,即參考資料[3])。
下面簡(jiǎn)單介紹文件系統(tǒng)的掛載。
一個(gè)文件系統(tǒng)可以通過一個(gè)設(shè)備掛載(mount)到某個(gè)目錄下(具體的實(shí)現(xiàn)請(qǐng)參考資料[2]和[1]),這個(gè)目錄被稱為掛載點(diǎn)。有趣的是,在Linux
下,一個(gè)目錄本身還可以掛載到另外一個(gè)目錄下,一個(gè)格式化了的文件也可以通過一個(gè)特殊的設(shè)備/dev/loop進(jìn)行掛載(如iso文件)。另外,就文件系
統(tǒng)而言,Linux不僅支持本地文件系統(tǒng),還支持遠(yuǎn)程文件系統(tǒng)(如nfs)。
下面簡(jiǎn)單介紹文件系統(tǒng)掛載的幾個(gè)實(shí)例。
A. 根文件系統(tǒng)的掛載
| Quote: |
|
// 掛載需要root權(quán)限,先切換到root用戶 // 掛載系統(tǒng)根文件系統(tǒng)/dev/sda1到一個(gè)新的目錄下 $ mount -t ext3 /dev/sda1 /mnt/ // 查看/dev/sda1的掛載情況,可以看到,一個(gè)設(shè)備可以多次掛載 $ mount | grep sda1 /dev/sda1 on / type ext3 (rw,errors=remount-ro) /dev/sda1 on /mnt type ext3 (rw) // 對(duì)于一個(gè)已經(jīng)掛載的文件系統(tǒng),為支持不同的屬性可以重新掛載 $ mount -n -o remount, rw /
|
B. 掛載一個(gè)新的設(shè)備
如果內(nèi)核已經(jīng)支持了USB接口,那么在插入u盤的時(shí)候,我們可以通過dmesg命令查看它對(duì)應(yīng)的設(shè)備號(hào),并掛載它。
| Quote: |
|
// 查看dmesg結(jié)果中的最后幾行內(nèi)容,找到類似/dev/sdN的信息,找出u盤對(duì)應(yīng)的設(shè)備號(hào) $ dmesg // 這里假設(shè)u盤是vfat格式的,以便在一些打印店里的windows上也可使用 $ mount -t vfat /dev/sdN /path/to/mountpoint_directory
|
C. 掛載一個(gè)iso文件或者是光盤
對(duì)于一些iso文件或者是iso格式的光盤,同樣可以通過mount命令掛載。
| Quote: |
|
// 對(duì)于iso文件 $ mount -t iso9660 /path/to/isofile /path/to/mountpoint_directory // 對(duì)于光盤 $ mount -t iso9660 /dev/cdrom /path/to/mountpoint_directory
|
D. 掛載一個(gè)遠(yuǎn)程文件系統(tǒng)
| Quote: |
|
$ mount -t nfs remote_ip:/path/to/share_directory /path/to/local_directory [quote] E. 掛載一個(gè)proc文件系統(tǒng) [quote] $ mount -t proc proc /proc
|
proc文件系統(tǒng)組織在內(nèi)存中,但是你可以把它掛載到某個(gè)目錄下。通常把它掛載在/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等文件),當(dāng)然,你也可以編寫自己的相關(guān)工具。
除此之外,通過調(diào)整/proc/sys目錄下的文件,你可以動(dòng)態(tài)的調(diào)整系統(tǒng)的配置,比如通過往
/proc/sys/net/ipv4/ip_forward文件中寫入數(shù)字1就可以讓內(nèi)核支持?jǐn)?shù)據(jù)包的轉(zhuǎn)發(fā)。(更多信息請(qǐng)參考proc的幫助,man
proc)
F. 掛載一個(gè)目錄
| Quote: |
|
$ mount --bind /path/to/needtomount_directory /path/to/mountpoint_directory
|
這個(gè)非常有意思,比如你可以把某個(gè)目錄掛載到ftp服務(wù)的根目錄下,而無須把內(nèi)容復(fù)制過去,就可以把相應(yīng)目錄中的資源提供給別人共享。
以上都只提到了掛載,那怎么卸載呢?用umount命令跟上掛載的源地址或者掛載點(diǎn)(設(shè)備,文件,遠(yuǎn)程目錄等)就可以。例如:
| Quote: |
|
$ umount /path/to/mountpoint_directory 或者 $ umount /path/to/mount_source
|
如果想管理大量的或者經(jīng)常性的掛載服務(wù),那么每次手動(dòng)掛載是很糟糕的事情。這個(gè)時(shí)候就可以利用mount的配置文件/etc/fstab,把mount對(duì)
應(yīng)的參數(shù)寫到/etc/fstab文件對(duì)應(yīng)的列中即可實(shí)現(xiàn)批量掛載(mount -a)和卸載(umount
-a)。/etc/fstab中各列分別為文件系統(tǒng)、掛載點(diǎn)、類型、相關(guān)選項(xiàng)。更多信息可參考fstab的幫助(man fstab)。
參考資料:
[1] Linux硬盤分區(qū)以及其掛載原理
http://www.xxlinux.com/linux/article/accidence/technique/20070521/8493.html
[2] 從文件I/O看linux的虛擬文件系統(tǒng)
http://www.ibm.com/developerworks/cn/linux/l-cn-vfs/
[3] 用Graphviz進(jìn)行可視化操作──繪制函數(shù)調(diào)用關(guān)系圖
http://oss.lzu.edu.cn/blog/blog.php?/do_showone/tid_1425.html
5 如何制作一個(gè)文件系統(tǒng)
Linux的文件系統(tǒng)下有一些最基本的目錄,不同的目錄下存放著不同作用的各類文件。最基本的目錄有/etc, /lib, /dev,
/bin等,它們分別存放著系統(tǒng)配置文件,庫(kù)文件,設(shè)備文件和可執(zhí)行程序。這些目錄一般情況下是必須的,在做嵌入式開發(fā)的時(shí)候,我們需要手動(dòng)或者是用
busybox等工具來創(chuàng)建這樣一個(gè)基本的文件系統(tǒng)。如何來制作一個(gè)這樣的文件系統(tǒng)呢?請(qǐng)參考資料[1]和[2]。這里我們制作僅制作一個(gè)非常簡(jiǎn)單的文件
系統(tǒng),并對(duì)該文件系統(tǒng)進(jìn)行各種常規(guī)的操作,以便加深對(duì)文件系統(tǒng)的理解。
首先,創(chuàng)建一個(gè)固定大小的文件。
| Quote: |
|
// 還記得dd命令么?我們就用它來產(chǎn)生一個(gè)固定大小的文件,這個(gè)為1M(1024*1024 bytes)的文件 $ dd if=/dev/zero of=minifs bs=1024 count=1024 // 查看文件類型,這里的minifs是一個(gè)充滿\0的文件,沒有任何特定的數(shù)據(jù)結(jié)構(gòu) $ file minifs minifs: data
|
說明:/dev/zero是一個(gè)非常特殊的設(shè)備,如果讀取它,可以獲取任意多個(gè)\0。
接著把該文件格式化為某個(gè)指定文件類型的文件系統(tǒng)。(是不是覺得不可思議,文件也可以格式化?是的,不光是設(shè)備可以,文件也可以以某種文件系統(tǒng)類型進(jìn)行組織,但是需要注意的是,某些文件系統(tǒng)(如ext3)要求被格式化的目標(biāo)最少有64M的空間)。
| Quote: |
|
// 格式化文件 $ mkfs.ext2 minifs // 查看此時(shí)的文件類型,這個(gè)時(shí)候文件minifs就以ext2文件系統(tǒng)的格式組織了 $ file minifs minifs: Linux rev 1.0 ext2 filesystem data
|
因?yàn)樵撐募晕募到y(tǒng)的類型組織了,那么可以用mount命令掛載并使用它。
| Quote: |
|
// 請(qǐng)切換到root用戶掛載它,并通過-o loop選項(xiàng)把它關(guān)聯(lián)到一個(gè)特殊設(shè)備/dev/loop $ mount minifs /mnt/ -o loop // 查看該文件系統(tǒng)的信息,僅可以看到一個(gè)目錄文件lost+found $ ls /mnt/ lost+found
|
在該文件系統(tǒng)下進(jìn)行各種常規(guī)操作,包括讀、寫、刪除等。(每次操作前先把minifs文件保存一份,以便比較,結(jié)合相關(guān)資料就可以深入地分析各種操作對(duì)文件系統(tǒng)的改變情況,從而深入理解文件系統(tǒng)作為一種組織數(shù)據(jù)的方式的實(shí)現(xiàn)原理等)
| Quote: |
|
$ 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)建一個(gè)文件后,比較此時(shí)文件系統(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):添加一個(gè)文件后,文件系統(tǒng)的相應(yīng)位置發(fā)生了明顯的變化 $ echo "hello, world" > /mnt/hello // 執(zhí)行sync命令,確保緩存中的數(shù)據(jù)已經(jīng)寫入磁盤(還記得附圖[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):刪除文件時(shí)并沒有覆蓋文件的內(nèi)容,所以從理論上說內(nèi)容此時(shí)還是可恢復(fù)的 $ strings minifs lost+found hello hello, world
|
上面僅僅演示了一些分析文件系統(tǒng)的常用工具,并分析了幾個(gè)常規(guī)的操作,如果你想非常深入地理解文件系統(tǒng)的實(shí)現(xiàn)原理,請(qǐng)熟悉使用上述工具并閱讀相關(guān)資料,比如1節(jié)的參考資料[2][3][4]。
參考資料:
[1] Build a mini filesystem in linux from scratch
http://oss.lzu.edu.cn/blog/blog.php?/do_showone/tid_1211.html
[2] Build a mini filesystem in linux with BusyBox
http://oss.lzu.edu.cn/blog/blog.php?/do_showone/tid_1212.html
[3] ext2 文件系統(tǒng)
http://man.chinaunix.net/tech/lyceum/linuxK/fs/filesystem.html
6 如何開發(fā)自己的文件系統(tǒng)
隨著fuse的出現(xiàn),在用戶空間開發(fā)文件系統(tǒng)成為可能,如果想開發(fā)自己的文件系統(tǒng),那么閱讀下面的參考資料吧。
參考資料:
[1] 使用fuse開發(fā)自己的文件系統(tǒng)
后記:
[1] 2007年12月22日,收集了很多資料,寫了整體的框架。
[2] 2007年12月28日下午,完成初稿,考慮到時(shí)間關(guān)系,很多細(xì)節(jié)也沒有進(jìn)一步分析,另外有些部分可能存在理解上的問題,歡迎批評(píng)指正。
[3] 2007年12月28日晚,修改部分資料,并正式公開該篇文檔。
[4] 29號(hào),添加設(shè)備驅(qū)動(dòng)和硬件設(shè)備一小節(jié)。