initramfs 簡介

轉自http://blog.csdn.net/future_fighter/article/details/3866068


initramfs 簡介,一個新的 initial RAM disks 模型
by Rob Landley, TimeSys (Mar. 15, 2005)

問題

當 Linux 內核啓動系統時,它必須找到並執行第一個用戶程序,通常是 init。用戶程序存在於文件系統,故 Linux 內核必須找到並掛載上第一個(根)文件系統,方能成功開機。
通常,可用的文件系統都列在 /etc/fstab,所以 mount 可以找到它們。但 /etc/fstab 它本身就是一個文件,存在於文件系統中。找到第一個文件系統成爲雞生蛋蛋生雞的問題,而且爲了解決它,內核開發者建立內核命令列選項 root=,用來指定 root 文件系統存在於哪個設備上。

十五年前,root= 很容易解釋。它可以是軟盤或硬盤上的分區。如今 root 文件系統可以存在於各種不同類型的硬件(SCSI, SATA, flash MTD) ,或是由不同類型硬件所建立的 RAID 上。它的位置隨着不同啓動而不同,像可熱插拔的 USB 設備被插到有多個 USB 孔的系統上 - 當有多個 USB 設備時,哪一個是正確的?root 文件系統也可能被壓縮(如何?),被加密(用什麼 keys?),或 loopback 掛載(哪裏?)。它甚至可以存在外部的網絡服務器,需要內核去取得 DHCP 地址,完成 DNS lookup,並登入到遠程服務器(需賬號及密碼),全部都在內核可以找到並執行第一個 userspace 程序之前。

如今,root= 已沒有足夠的信息。即使將所有特殊案例的行爲都放進內核也無法幫助設備列舉,加密,或網絡登入這些隨着系統不同而不同的系統。更糟的是,替核心加入這些複雜的工作,就像是用彙編語言寫 web 軟件 :可以做到,但使用適當的工具會更容易完成。核心是被設計成服從命令,而不是給命令。

爲了這個不斷增加複雜度的工作, 核心開發者決定去尋求更好的方法來解決這整個問題。

解決方法

Linux 2.6 核心將一個小的 ram-based initial root filesystem(initramfs) 包進內核,且若這個文件系統包含一個程序 init,核心會將它當作第一個程序執行。此時,找尋其它文件系統並執行其它程序已不再是內核的問題,而是新程序的工作。

initramfs 的內容不需是一般功能。若給定系統的 root 文件系統存在於一個加密過的網絡塊設備,且網絡地址、登入、加密都存在 USB 設備 "larry" (需密碼方能存取)裏,系統的 initramfs 可以有特殊功能的程序,它知道這些事,並使這可以運作。

對系統而言,不需要很大的 root 文件系統,也不需要尋址或切換到任何其它 root 文件系統。
這跟 initrd 有何不同?

Linux kernel 已經有方法提供 ram-based root filesystem,initrd 機制。對 2.4 及更早的 kernel 來說,initrd 仍然是唯一的方法去做這一連串的事。但 kernel 開發者選擇在 2.6 實現一個新的機制是有原因的。

ramdisk vs ramfs

ramdisk (如 initrd) 是 基於ram的塊設備,這表明它是一塊固定大小的內存,它可以被格式化及掛載,就像磁盤一樣。這表明 ramdisk 的內容需先格式化並用特殊的工具(像是 mke2fs 及 losetup)做前置作業,而且如同所有的塊設備,它需要文件系統驅動程序在執行時期解釋數據。這也有人工的大小限制不論是浪費空間(若 ramdisk 沒有滿,已被佔用的額外的內存也不能用來做其它事)或容量限制(若 ramdisk 滿了,但其它仍有閒置的內存,也不能不經由重新格式化將它擴展)。

但 ramdisk 由於緩衝機制(caching)實際上浪費了更多內存。Linux 被設計爲將所有的文件及目錄做緩存,不論是對塊設備的讀出或寫入,所以 Linux 複製數據到 ramdisk及從 ramdisk 複製數據出來,page cache 給 file data 用,而 dentry cache 給目錄用。ramdisk 的下面則僞裝爲塊設備。

幾年前,Linus Torvalds 有一個巧妙的想法:Linux 的緩存是否可以被掛載一個文件系統?只要保持文件在緩存中且不要將它們清除,直到它們被刪除或系統重新啓動?Linus 寫了一小段程序將緩存包起來,稱它爲 ramfs,而其它的 kernel 開發者建立一個加強版本稱爲 tmpfs(它可以寫數據到 swap,及限制掛載點的大小,所以在它消耗完所有可用的內存前它會填滿)。initramfs 就是 tmpfs 的一個實例。
這些基於ram的文件系統自己改變大小以符合數據所需的大小。增加文件到 ramfs(或增大原有的文件)會自動配置更多的內存,並刪除或截去文件以釋放內存。在塊設備及緩存間沒有複製動作,因爲沒有實際的塊設備。在緩存中的只是數據的複製。更好的是這並不是新的程序代碼,而是已存在的 Linux 緩存程序代碼新的應用,這表示它幾乎沒有增加大小,非常簡單,且基於已經歷測試的基礎上。

系統使用 initramfs 作爲它的 root 文件系統甚至不需要將文件系統驅動程序內建到 kernel,因爲沒有塊設備要用來做文件服務器。只是存在內存中的文件罷了。

initrd vs initramfs

底層架構的改變是 kernel 開發者建立一個新的實現的理由,但當他們在那裏時他們清除了很多不好的行爲及假設。
initrd 被設計爲舊的 root= 的 root 設備檢測程序代碼的前端,而不是取代它。它執行 /linuxrc,這被用來完成設定功能(像是登入網絡,決定哪個設備含有 root 分區,或用文件做爲 loopback 設備),告訴 kernel 哪個塊設備含有真的 root 設備(通過寫入de_t 數據到 /proc/sys/kernel/real-root-dev),且回傳給 kernel,所以 kernel 可以掛載真的 root 設備及執行真的 init 程序。

這裏假設“真的根設備”是塊設備而不是網絡共享的,同時也假設 initrd 自己不是做爲真的 root 文件系統。kernel 也不會執行 /linuxrc 而做爲特殊的進程(ID=1),因爲這個 process ID(它有特殊的屬性,像是做爲唯一無法被以 kill -9 的 process) 被保留給 init,kernel 在它掛載真的 root 文件系統後會等它執行。

用 initramfs,kernel 開發者移除所有的假設。當 kernel 啓動了在 initramfs 外的 /init,kernel 即做好決定並回去等待接受命令。用 initramfs,kernel 不需要關心真的 root 檔案系統在哪裏,而在 initramfs 的 /init 被執行爲真的 init,以 PID 1。(若 initramfs 的 init 需要不干涉特別的 PID 給其它程序,它可以用 exec() 系統呼叫,就像其它人一樣)

總結

傳統的 root= kernel 命令列選項仍然被支持且可用。但在開發支持initial RAM disk支持內核時,提供了許多優化和靈活性。

譯者注

  1. 查看initramfs的內容# mkdir initrd
    # cd intrd
    # cp /boot/initrd.img initrd.img
    # gunzip initrd.img
    # cpio -i --make-directories < initrd.img
    #
  2. 創建initramfs
    1. mkinitramf# mkinitramfs -o /boot/initrd.img 2.6.2
      Note: 2.6.25是需要創建initramfs的kernel版本號,如果是給當前kernel製作initramfs,可以用uname -r查看當前的版本號。提供kernel版本號的主要目的是爲了在initramfs中添加指定kernel的驅動模塊。mkinitramfs會把/lib/modules/${kernel_version}/ 目錄下的一些啓動會用到的模塊添加到initramfs中。
    2. update-initramfs更新當前kernel的initramfs
      # update-initramfs -u
      在添加模塊時,initramfs tools只會添加一些必要模塊,用戶可以通過在/etc/initramfs-tools/modules文件中加入模塊名稱來指定必須添加的模塊。
    命令:mkinitramfs, update-initramfs
  3. mkinitcpio
    在Arch Linux中,有一個新一代的initramfs製作工具。相對於老的mkinitrd和mkinitramfs,它有以下很多優點。查看詳細《使用mkinitcpio》。
  4. 參考鏈接:
發佈了11 篇原創文章 · 獲贊 8 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章