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

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