1. 程式人生 > >根文件系統

根文件系統

src ole raw 基於 iso 命令行參數 part png tro

目錄

  • 根文件系統
    • 文件系統概念
    • 啟動流程
    • 根文件系統
      • ramdisk啟動
      • flash啟動
      • initramfs
      • initrd
    • 雞生蛋蛋生雞
    • 參考鏈接

title: 根文件系統
tags: linux
date: 2018-09-19 19:56:05
---

根文件系統

文件系統概念

文件系統是一些代碼,是一套軟件,這套軟件的功能就是對存儲設備的扇區進行管理,將這些扇區的訪問變成了對目錄和文件名的訪問。我們在上層按照特定的目錄和文件名去訪問一個文件時,文件系統會將這個目錄+文件名轉換成對扇區號的訪問。

  • 虛擬文件系統接口(VFS)是linux定義的一個文件系統的統一接口,這樣各種類型的文件系統都采用一樣的接口給用戶
  • 虛擬文件系統存儲在RAM裏的,沒有實際的設備(ROM)與之對應
  • 實際文件系統有實際的存儲設備(ROM)與之對應,又可分為遠程文件系統和本地文件系統
  • 根文件系統處於文件系統的最上層,其很重要的作用是用來掛載其他文件系統。根文件系統可以是虛擬文件系統也可以是實際文件系統,只要條件支持.
  • 文件系統格式 linux支持包括ext2,ext3,vfat,jffs,ramfs,nfs等文件系統
    • jffs2:主要用於nor型flash,特點是可讀寫,支持數據壓縮的日誌型文件系統。
    • yaffs/yaffs2:主要用於nand型flash,支持跨平臺。
    • cramfs:只讀的壓縮文件系統。可用於兩種flash。
    • ramdisk:基於ram的文件系統。是將一部分固定大小的內存當做塊設備來用。它並非是一個實際的文件系統,而是一種將實際的文件系統裝入內存的機制。將一些經常訪問而又無需更改的文件通過ramdisk放在內存中,可以明顯的提高系統的性能。
    • initramfs:基於ram的文件系統。initramfs出現在2.6內核中,它類似於tmpfs,是一種基於內存的文件系統,它的使用不需要創建內存塊設備。增加文件到ramfs會自動配置更多的內存,並刪除或截去文件以釋放內存。(若ramdisk沒有滿,已被占用的額外的內存也不能用來做其它事情,若ramdisk滿了,但其它仍有閑置的內存,也必須重新格式化以後才能擴展使用)
    • nfs:是由sun開發的一種在不同機器之間通過網絡共享文件的技術。在嵌入式linux系統的開發調試階段,可以利用該技術在主機上建立基於nfs的根文件系統,掛載到嵌入式設備,可以很方便的修改根文件系統的內容。

啟動流程

內核通過一系列初始化之後,掛載根文件系統來執行應用程序. 所謂根文件系統,需要提前按照一定的文件系統的格式化,並放入相應的內容數據.Kernel 根據啟動參數去尋找根文件系統的位置去mount

技術分享圖片

根文件系統

ramdisk啟動

  1. 制作ramdisk文件系統壓縮包
  2. 然後將這個文件壓縮包通過bootloader下載到內存中
  3. 當系統啟動的時候
    • 通過uboot的bootargs環境變量來傳遞啟動參數,修改為bootargs=initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64,以此指定從ramdisk啟動,ramdisk壓縮文件起始地址在內存地址0x31000000處,文件大小為0x200000。
    • 也可以通過修改內核配置Default kernel command string為”initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64”

flash啟動

文件系統存在FLASH ,內核根據命令行參數root=/dev/xxx,直接mount

問題? 在root文件系統本身還不存在的情況下,內核如何根據/dev/xxx來找到對應的設備呢?

解答: 根文件系統和其他文件系統的mount方式是不一樣的,內核通過直接解析設備的名稱來獲得設備的主、從設備號,然後就可以訪問對應的設備驅動了。所以在init/main.c中有很長一串的root_dev_names(如hda,hdab,sda,sdb,nfs,ram,mtdblock……),通過這個表就可以根據設備名稱得到設備號。註意,bootloader或內核中設定的啟動參數root=/dev/xxx只是一個代號,實際的根文件系統中不一定存在這個設備文件!

拿ARM來說,在文件arch/arm/plat-s3c24xx/common-smdk.c中有分區表:

static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name   = "Boot",
.size   = 0x00020000,
.offset = 0,
},
[1] = {
.name   = "Kernel",
.size   = 0x00240000,
.offset = 0x00040000,
},
[2] = {
.name   = "RootFileSystem",
.size   = 0x02000000,
.offset = 0x00280000,
},
[3] = {
.name   = "ExtendFileSystem",
.size   = 0x05d80000,
.offset = 0x02280000,
    }
};

initramfs

initramfs將根目錄直接編譯到linux內核鏡像中 ,這種方法不同於前面兩種方法需要在uboot啟動參數中指定ramdisk加載到內存的地址或者文件系統在flash中的分區,由於已經將根目錄編譯到linux的.init.ramfs段中了,所以啟動的時候直接將linux內核鏡像的.init.ramfs段的內容解壓到系統的rootfs中。

initrd

啟動時用到initrd來mount根文件系統。註意理解ramdisk和initrd這兩個概念,其實ramdisk只是在ram上實現的塊設備,類似與硬盤操作,但有更快的讀寫速度,它可以在系統運行的任何時候使用,而不僅僅是用於啟動;

initrd(boot loader initialized RAM disk)可以說是啟動過程中用到的一種機制,具體的實現過程也使用ramdisk技術。就是在裝載linux之前,bootloader可以把一個比較小的根文件系統的映象裝載在內存的某個指定位置,姑且把這段內存稱為initrd(這裏是initrd所占的內存,不是ramdisk,註意區別),然後bootloader通過傳遞參數的方式告訴內核initrd的起始地址和大小(也可以把這些參數編譯在內核中),在啟動階段就可以暫時的用initrd來mount根文件系統。initrd的最初的目的是為了把kernel的啟動分成兩個階段:在kernel中保留最少最基本的啟動代碼,然後把對各種各樣硬件設備的支持以模塊的方式放在initrd中,這樣就在啟動過程中可以從initrd所mount的根文件系統中裝載需要的模塊。這樣的一個好處就是在保持kernel不變的情況下,通過修改initrd中的內容就可以靈活的支持不同的硬件。在啟動完成的最後階段,根文件系統可以重新mount到其他設備上,但是也可以不再 重新mount(很多嵌入式系統就是這樣)。 initrd的具體實現過程是這樣的:bootloader把根文件系統映象裝載到內存指定位置,把相關參數傳遞給內核,內核啟動時把initrd中的內容復制到ramdisk中(ram0),把initrd占用的內存釋放掉,在ram0上mount根文件系統。從這個過程可以看出,內核需要對同時對ramdisk和initrd的支持(這種需要都編入內核,不能作為模塊)。

雞生蛋蛋生雞

內核剛啟動時,磁盤設備、網絡設備都還沒有被驅動起來,所以無法訪問磁盤,沒法給磁盤啟用對應的文件系統。那趕緊安裝磁盤驅動程序,網絡驅動程序呀,怎麽不加載呢?因為磁盤種類太多了,沒法把所有的驅動都編譯到內核裏頭,那樣內核得變得多大呀,所以就只能把這些驅動程序編譯成模塊的方式,在內核加載的時候現場判斷當前用的是什麽磁盤再加相應的磁盤驅動模塊。那就加載磁盤驅動模塊呀,等什麽呢?原因是編譯成驅動模塊後,在這個階段壓根就沒法加載!還沒文件系統呢,怎麽加載驅動模塊?結果啟用文件系統的前提是磁盤的驅動程序已經加載,而驅動程序的加載的前提是已經有文件系統存在,這就成了雞生蛋,蛋生雞的問題,怎麽破?想到內核加載的時候,RAM其實已經可用了,那就基於RAM建立一個臨時文件系統吧,這個臨時的文件系統自己掛載到自己身上,然後我們指定這個文件系統為根文件系統,這樣就有了起步的文件系統啦,借助這個臨時的文件系統把磁盤驅動模塊、網絡驅動模塊加載上,這樣就可以掛載實際的文件系統啦,有了實際的文件系統之後再把這個實際的文件系統指定為根文件系統,這就好啦,然後其他的各式各樣的文件系統就可以陸陸續續的掛載在這個根文件系統下了。
回到之前的一個問題,怎麽建立一個基於RAM的虛擬文件系統?首先,在編譯內核得時候就編譯一個很精簡的虛擬文件系統進去,然後內核在啟動的時候先註冊一個rootfs這個虛擬文件系統,然後掛載這個虛擬文件系統,那rootfs這個虛擬文件還是個空的,得給裏頭放點東西呀,放什麽呢?就放編譯進內核裏頭的那個很精簡的虛擬文件系統裏的內容。怎麽內容放進rootfs裏去?方法簡單粗暴,直接把編譯進內核裏頭的那個很精簡的虛擬文件系統裏的內容解壓到rootfs裏,這個過程叫填充rootfs。

參考鏈接

“文件系統”與“根文件系統”詳解

linux啟動根文件系統

知乎:何為文件系統,何為根文件系統?

cnblog 根文件系統原理

根文件系統