1. 程式人生 > >淺談linux中的根檔案系統(rootfs的原理和介紹)

淺談linux中的根檔案系統(rootfs的原理和介紹)

linux中有一個讓很多初學者都不是特別清楚的概念,叫做“根檔案系統”。我接觸linux前前後後也好幾年了,但是對這個問題,至今也不是特別的清楚,至少沒法給出一個很全面很到位的解釋。於是,今天我們就來理一理這個話題。

一、先交代一下檔案系統

在開始討論根檔案系統這個話題之前,我們必首先交代一下檔案系統這個概念。畢竟,根檔案系統只是檔案系統中的一種比較特殊的形式而已。根據偉大的百度百科:

檔案系統是作業系統用於明確儲存裝置(常見的是磁碟,也有基於NAND Flash的固態硬碟)或分割槽上的檔案的方法和資料結構;即在儲存裝置上組織檔案的方法。作業系統中負責管理和儲存檔案資訊的軟體機構稱為檔案管理系統,簡稱檔案系統。檔案系統由三部分組成:檔案系統的介面,對物件操作和管理的軟體集合,物件及屬性。從系統角度來看,檔案系統是對檔案儲存裝置的空間進行組織和分配,負責檔案儲存並對存入的檔案進行保護和檢索的系統。具體地說,它負責為使用者建立檔案,存入、讀出、修改、轉儲檔案,控制檔案的存取,當用戶不再使用時撤銷檔案等。

檔案系統的重要性,我想大家都很清楚,不用多說了。這裡有一句話,我覺得非常精闢而且到位的點出了檔案系統在linux中的重要性:

儘管核心是linux的核心,但檔案卻是使用者與作業系統互動所採用的主要工具。這對linux來說尤其如此,這是因為在UNIX傳統中,它使用檔案I/O機制管理硬體裝置和資料檔案。

二、什麼是根檔案系統

然後來解釋一下“根檔案系統”這個名詞的基本概念。同樣引自百度百科的解釋:

根檔案系統首先是核心啟動時所mount的第一個檔案系統,核心程式碼映像檔案儲存在根檔案系統中,而系統引導啟動程式會在根檔案系統掛載之後從中把一些基本的初始化指令碼和服務等載入到記憶體中去執行。

展開來細說就是,根檔案系統首先是一種檔案系統,該檔案系統不僅具有普通檔案系統的儲存資料檔案的功能,但是相對於普通的檔案系統,它的特殊之處在於,它是核心啟動時所掛載(mount)的第一個檔案系統,核心程式碼的映像檔案儲存在根檔案系統中,系統引導啟動程式會在根檔案系統掛載之後從中把一些初始化指令碼(如rcS,inittab)和服務載入到記憶體中去執行。我們要明白檔案系統和核心是完全獨立的兩個部分。在嵌入式中移植的核心下載到開發板上,是沒有辦法真正的啟動Linux作業系統的,會出現無法載入檔案系統的錯誤。

三、根檔案系統為什麼這麼重要

根檔案系統之所以在前面加一個”根“,說明它是載入其它檔案系統的”根“,那麼如果沒有這個根,其它的檔案系統也就沒有辦法進行載入的。

根檔案系統包含系統啟動時所必須的目錄和關鍵性的檔案,以及使其他檔案系統得以掛載(mount)所必要的檔案。例如:

  1. init程序的應用程式必須執行在根檔案系統上;
  2. 根檔案系統提供了根目錄“/”;
  3. linux掛載分割槽時所依賴的資訊存放於根檔案系統/etc/fstab這個檔案中;
  4. shell命令程式必須執行在根檔案系統上,譬如ls、cd等命令;

總之:一套linux體系,只有核心本身是不能工作的,必須要rootfs(上的etc目錄下的配置檔案、/bin /sbin等目錄下的shell命令,還有/lib目錄下的庫檔案等···)相配合才能工作。

Linux啟動時,第一個必須掛載的是根檔案系統;若系統不能從指定裝置上掛載根檔案系統,則系統會出錯而退出啟動。成功之後可以自動或手動掛載其他的檔案系統。因此,一個系統中可以同時存在不同的檔案系統。在 Linux 中將一個檔案系統與一個儲存裝置關聯起來的過程稱為掛載(mount)。使用 mount 命令將一個檔案系統附著到當前檔案系統層次結構中(根)。在執行掛裝時,要提供檔案系統型別、檔案系統和一個掛裝點。根檔案系統被掛載到根目錄下“/”上後,在根目錄下就有根檔案系統的各個目錄,檔案:/bin /sbin /mnt等,再將其他分割槽掛接到/mnt目錄上,/mnt目錄下就有這個分割槽的各個目錄和檔案。

四、如何在核心中掛載根檔案系統

init/main.c->

 start_kernel()->vfs_caches_init(totalram_pages)–>

   mnt_init()–>

     /* sysfs用來記錄和展示linux驅動模型,sysfs先於rootfs掛載是為全面展示linux驅動模型做好準備 */
     /* mnt_init()呼叫sysfs_init()註冊並掛載sysfs檔案系統,然後呼叫kobject_create_and_add()建立fs目錄 */
     sysfs_init();

     /* init_rootfs()註冊rootfs,然後呼叫init_mount_tree()掛載rootfs */
     init_rootfs();

     init_mount_tree();

1、sysfs檔案系統目前還沒有掛載到rootfs的某個掛載點上,後續init程式會把sysfs掛載到rootfs的sys掛載點上;

2、rootfs是基於記憶體的檔案系統,所有操作都在記憶體中完成;也沒有實際的儲存裝置,所以不需要裝置驅動程式的參與。基於以上原因,linux在啟動階段使用rootfs檔案系統,當磁碟驅動程式和磁碟檔案系統成功載入後,linux系統會將系統根目錄從rootfs切換到磁碟檔案系統。

start_kernel
  vfs_caches_init
    mnt_init
      init_rootfs註冊rootfs檔案系統
      init_mount_tree 掛載rootfs檔案系統
        vfs_kern_mount
          mount_fs
            type->mount其實是rootfs_mount
              mount_nodev
                fill_super 其實是ramfs_fill_super
                  inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
                  sb->s_root = d_make_root(inode);
                    static const struct qstr name = QSTR_INIT(“/”, 1);[1*]
                    __d_alloc(root_inode->i_sb, &name);
          …
          mnt->mnt.mnt_root = root;[2*]
          mnt->mnt.mnt_sb = root->d_sb;[3*]
          mnt->mnt_mountpoint = mnt->mnt.mnt_root;[4*]
          mnt->mnt_parent = mnt;[5*]
root.mnt = mnt;
        root.dentry = mnt->mnt_root;
        mnt->mnt_flags |= MNT_LOCKED;
        set_fs_pwd(current->fs, &root);
        set_fs_root(current->fs, &root);
  …
  rest_init
  kernel_thread(kernel_init, NULL, CLONE_FS);

在執行kernel_init之前,會建立roofs檔案系統。

[1*]處設定了根目錄的名字為“/”;
[2*]處設定了vfsmount中的root目錄;
[3*]處設定了vfsmount中的超級塊;
[4*]處設定了vfsmount中的檔案掛載點,指向了自己;
[5*]處設定了vfsmount中的父檔案系統的vfsmount為自己;

五、根檔案系統各個常用目錄簡介

正常來說,根檔案系統至少包括以下目錄:

  1. /etc/:儲存重要的配置檔案。
  2. /bin/:儲存常用且開機時必須用到的執行檔案。
  3. /sbin/:儲存著開機過程中所需的系統執行檔案。
  4. /lib/:儲存/bin/及/sbin/的執行檔案所需的連結庫,以及Linux的核心模組。
  5. /dev/:儲存裝置檔案。

注:五大目錄必須儲存在根檔案系統上,缺一不可。

六、順便說下linux檔案系統的常用目錄

Linux檔案系統中一般有如下幾個目錄:

  1. /bin目錄
    該目錄下存放所有使用者都可以使用的、基本的命令,這些命令在掛接其它檔案系統之前就可以使用,所以/bin目錄必須和根檔案系統在同一個分割槽中。
    /bin目錄下常用的命令有:cat,chgrp,chmod,cp,ls,sh,kill,mount,umount,mkdir,mknod,test等,我們在利用Busybox製作根檔案系統時,在生成的bin目錄下,可以看到一些可執行的檔案,也就是可用的一些命令。

  2. /sbin 目錄
    該目錄下存放系統命令,即只有管理員能夠使用的命令,系統命令還可以存放在/usr/sbin,/usr/local/sbin目錄下,/sbin目錄中存放的是基本的系統命令,它們用於啟動系統,修復系統等,與/bin目錄相似,在掛接其他檔案系統之前就可以使用/sbin,所以/sbin目錄必須和根檔案系統在同一個分割槽中。
    /sbin目錄下常用的命令有:shutdown,reboot,fdisk,fsck等,本地使用者自己安裝的系統命令放在/usr/local/sbin目錄下。

  3. /dev目錄
    該目錄下存放的是裝置檔案,裝置檔案是Linux中特有的檔案型別,在Linux系統下,以檔案的方式訪問各種裝置,即通過讀寫某個裝置檔案操作某個具體硬體。比如通過”dev/ttySAC0”檔案可以操作串列埠0,通過”/dev/mtdblock1”可以訪問MTD裝置的第2個分割槽。

  4. /etc目錄
    該目錄下存放著各種配置檔案,對於PC上的Linux系統,/etc目錄下的檔案和目錄非常多,這些目錄檔案是可選的,它們依賴於系統中所擁有的應用程式,依賴於這些程式是否需要配置檔案。在嵌入式系統中,這些內容可以大為精減。

  5. /lib目錄
    該目錄下存放共享庫和可載入(驅動程式),共享庫用於啟動系統。執行根檔案系統中的可執行程式,比如:/bin /sbin 目錄下的程式。

  6. /home目錄
    使用者目錄,它是可選的,對於每個普通使用者,在/home目錄下都有一個以使用者名稱命名的子目錄,裡面存放使用者相關的配置檔案。

  7. /root目錄
    根使用者的目錄,與此對應,普通使用者的目錄是/home下的某個子目錄。

  8. /usr目錄
    /usr目錄的內容可以存在另一個分割槽中,在系統啟動後再掛接到根檔案系統中的/usr目錄下。裡面存放的是共享、只讀的程式和資料,這表明/usr目錄下的內容可以在多個主機間共享,這些主要也符合FHS標準的。/usr中的檔案應該是隻讀的,其他主機相關的,可變的檔案應該儲存在其他目錄下,比如/var。/usr目錄在嵌入式中可以精減。

  9. /var目錄
    與/usr目錄相反,/var目錄中存放可變的資料,比如spool目錄(mail,news),log檔案,臨時檔案。

  10. /proc目錄
    這是一個空目錄,常作為proc檔案系統的掛接點,proc檔案系統是個虛擬的檔案系統,它沒有實際的儲存裝置,裡面的目錄,檔案都是由核心臨時生成的,用來表示系統的執行狀態,也可以操作其中的檔案控制系統。

  11. /mnt目錄
    用於臨時掛載某個檔案系統的掛接點,通常是空目錄,也可以在裡面建立一引起空的子目錄,比如/mnt/cdram /mnt/hda1 。用來臨時掛載光碟、硬碟。

  12. /tmp目錄
    用於存放臨時檔案,通常是空目錄,一些需要生成臨時檔案的程式用到的/tmp目錄下,所以/tmp目錄必須存在並可以訪問。