1. 程式人生 > >shell程式設計範例之檔案系統操作

shell程式設計範例之檔案系統操作

前言


    準備了很久,找了好多天的資料,還不知道應該如何開始動筆寫:因為擔心“拿捏”不住,所以一方面繼續查詢資料,一方面思考如何來寫。作為“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號,新增裝置驅動和硬體裝置一小節。

相關推薦

shell程式設計範例檔案系統操作

前言     準備了很久,找了好多天的資料,還不知道應該如何開始動筆寫:因為擔心“拿捏”不住,所以一方面繼續查詢資料,一方面思考如何來寫。作為“shell程式設計 範例”序列的一部分,希望它能夠很好地幫助shell程式設計師理解如何用shell命令來完成和Linux系統

[授權發表]Shell程式設計範例檔案操作

前言 這一週我們來探討檔案操作。 在日常學習和工作中,我們總是在不斷地和各種檔案打交道,這些檔案包括普通的文字檔案,可以執行的程式檔案,帶有控制字元的文件、存放各種檔案的目錄檔案、網路套接字檔案、裝置檔案等。這些檔案又具有諸如屬主、大小、建立和修

shell程式設計範例程序操作

by falcon<[email protected]> 2008-02-21     這一小節寫了很久,到現在才寫完。本來關注的內容比較多,包括程式開發過程的細節、ELF格式的分析、程序的記憶體映像等,後來搞得“雪球越滾越大”,甚至 脫離了shell

shell程式設計範例字串操作[轉]

shell程式設計範例之字串操作下面是"線上新華字典"的解釋: 字串:簡稱“串”。有限字元的序列。資料元素為字元的線性表,是一種資料的邏輯結構。在計算機中可有不同的儲存結構。在串上可進行求子串、插入字元、刪除字元、置換字元等運算。 而字元呢? 字元:計算機程式設計及操作時使用的符號。包括字母、數字、空格符、

Linux高階程式設計基礎——檔案系統程式設計檔案寫入操作

檔案系統程式設計之檔案寫入操作——實驗題 //編寫程式碼,完成以下功能: //1.建立檔案file1,寫入字串“abcdefghijklmn”; //2.建立檔案file2,寫入字串“ABCDEFGHIJKLMN”; //3.讀取file1中的內容,寫入file2,使file2中的字串內容為“a

shell命令列檔案操作

【檔案操作】 1、反選刪除檔案 先執行:shopt -s extglob 再執行:rm -rf !(file1) rm -rf !(file1|file2) 2、清空檔案內容 :> file 【磁碟管理】 1、檢視當前目錄下個檔

C語言嵌入式系統程式設計修煉三:記憶體操作

資料指標  在嵌入式系統的程式設計中,常常要求在特定的記憶體單元讀寫內容,彙編有對應的MOV指令,而除C/C++以外的其它程式語言基本沒有直接訪問絕對地址的能力。在嵌入式系統的實際除錯中,多借助C語言指標所具有的對絕對地址單元內容的讀寫能力。以指標直接操作記憶體多發生在如下

Linux 核心程式設計檔案系統(二)

1.為了方便查詢,VFS引入了 目錄 項,每個dentry代表路徑中的一個特定部分。目錄項也可包括安裝點。 2.目錄項物件由dentry結構體表示 ,定義在檔案linux/dcache.h 標頭檔案中。   89struct dentry {  90        atomic_t d_count;     

系統程式設計檔案系統程式設計

系統呼叫:所有的作業系統都提供多種服務的入口點,程式由此向核心請求服務。這些可直接進入核心的入口點被稱為系統呼叫。 不同作業系統提供了自己的一套系統呼叫,所以系統呼叫無法實現跨平臺使用。而且頻繁地系統

Shell程式設計---批量建立檔案

1) 請使用for迴圈在指定的/yuki目錄下建立10個檔案,檔名分別為: yuki-1.html, yuki-2.html, yuki-3.html, ..... yuki-10.html 分析: 所有檔名首尾相同,只是中間部分以數字的規律變化了,所以檔名可以用數字迴

OC學習篇---檔案操作

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

bash學習檔案系統(七)

linux系統的一個特點就是將所有的內容都看作是檔案。因此至少要了解linux的檔案也是一個重要的內容。下面將介紹一下linux裡面的檔案: 1.按照檔案型別進行劃分 文字檔案: 檔案的組成主要是ASCII碼,也就是能夠直接識別成我能能夠讀懂內容是什麼的檔案(windows的tx

Linux學習檔案系統管理——回顧分割槽和檔案系統

一、回顧分割槽和檔案系統 1、分割槽型別: 》主分割槽:總共最多隻能分四個 》擴充套件分割槽:只能有一個,也算作主分割槽的一種,也就是說主分割槽加擴充套件分割槽最多有四個。但是擴充套件分球不能儲存資料和格式化,必須再劃分成邏輯分割槽才能使用。 》邏輯分割槽:邏輯分割槽是在擴充套件

《笨兔兔的故事》檔案系統部分讀書心得

最近看了一本電子書,書名叫《笨兔兔的故事》,乍一聽書名,是不是以為是童話故事書?實際上它是一本介紹linux系統的技術書籍,作者通過趣味幽默的筆觸,把很多乏味難讀的技術文章,通過笨兔兔這個小動物以第一人稱生動表達,非常適合初學者,或者即使有經驗的同事把它當趣味小說也能串聯複習

centos檔案系統操作

linux系統與windows操作區別還是很大的。 我們先來看下檔案系統這一塊,在windows系統中,我們存放的檔案都是存在在磁碟中的資料夾。那麼在linux系統中沒有磁碟的這中概念。 那麼linux中 是以目錄的形式來區分。 我們先來熟悉 兩個命令  ls 和 ll&nbs

Linux命令——檔案系統命令

目錄 df: mv:移動 linux系統常見重要檔案目錄 Filesystem Hierarchy Standard(檔案系統層次化標準) /boot:系統啟動相關的檔案,如核心、initrd,

Linux學習檔案系統管理-檔案系統常用命令

一、檔案系統常用命令-df、du、fsck、dumpe2fs 1、檔案系統檢視命令df: [[email protected] ~]# df  【選項】【掛載點】 選項:   -a   顯示所有的檔案系統資訊,包括特殊檔案系統,如/proc

深入理解作業系統原理檔案系統

一、概述 作業系統對系統的軟體資源(不論是應用軟體和系統軟體)的管理都以檔案方式進行,承擔這部分功能的作業系統稱為檔案系統。 1、檔案 計算機系統對系統中軟體資源:無論是程式或資料、系統軟體或應用軟體都以檔案方式來管理。檔案是存貯在某種介質上的(如磁碟

shell程式設計vim多個視窗操作

$ vim -o filename1 filename2   縱向分割顯示: $ vim -O filename1 filename2 二、如果已經用vim打開了一個檔案,想要在視窗中同時再開啟另一個檔案: 橫向分割顯示: :vs filename 縱向分割顯示: :sp filename

系統程式設計概念(檔案系統mount等函式的使用)

掛載檔案系統 #include<sys/mount.h> int mount(const char *source,const char *target,const char *fstyp