2. 解決方案
2.1 ramdisk(好比initrd)
2.2 tmpfs(好比initramfs)
2.3 ramdisk vs ramfs
2.4 臨時文件系統
2.4.1 觀察tmpfs
2.4.2 Initramfs
2.4.3 查看initramfs
2.4.4 建立initramfs
2.5 Linux系統中的initramfs
2.6 cpio歸檔文件
3. 高級用戶
3.1 製做本身的initramfs
3.2 Initramfs編程
3.3 使用更新的工具
1. 內核啓動問題
當Linux內核引導系統時,它必須找到並運行第一個用戶程序,一般稱爲「init」。(大多數較新的版本使用systemd做爲默認init)用戶程序存在於文件系統中,所以Linux內核必須找到並掛載第一個(或「根」)文件系統才能成功啓動。
一般,可用的文件系統列在文件 /etc/fstab 中,經過 mount 程序能夠找到它們。可是 /etc/fstab 自己就是一個存儲在文件系統中的文件。
找到第一個文件系統是雞和蛋的問題,爲了解決這個問題,內核開發人員建立了內核命令行選項「root =」,以指定根文件系統所在的設備。
二十年前,「root =」很容易解釋。它多是軟盤驅動器,也多是硬盤驅動器上的分區。(可用硬件設備及文件系統很是少,很容易指定)
如今,根文件系統能夠在幾十種不一樣類型的硬件上,文件系統也有幾十種,甚至能夠在RAID中分佈在其中的幾種硬件上。壓縮,加密,環回掛載,存在與網絡上等等狀況。
新的硬件,新的文件系統,新的壓縮,加密方法還會愈來愈多。
2. 解決方案
爲了不將如此多的特殊狀況硬編碼到內核中,使用了具備臨時根文件系統的初始啓動階段 - 如今稱爲早期用戶空間。此根文件系統能夠包含用戶空間幫助程序,它們執行硬件檢測,模塊加載和設備發現,以便安裝真正的根文件系統。2.1 ramdisk(好比initrd)
在2.4及更早版本上,主要使用ramdisk(好比initrd), 基於ram的塊設備, 但因爲模仿塊設備,致使它是固定大小的內存塊,須要像磁盤同樣進行格式化和安裝,(操做工具mke2fs,losetup)。須要文件系統驅動。這形成額外的開銷,資源的浪費。固定的大小還不能擴展。2.2 tmpfs(好比initramfs)
Rootfs是ramfs(或tmpfs,若是已啓用)的特殊實例,具體表現好比Initramfs文件。到2.6版本時期,Linus在緩存周圍寫了一個名爲「ramfs」的小包裝器,Ramfs是一個很是簡單的文件系統,它將Linux的磁盤緩存機制(頁面緩存和dentry緩存)導出爲可動態調整大小的基於RAM的文件系統。
ramfs的一個缺點是你能夠繼續寫入數據直到你填滿全部內存,而VM沒法釋放它,由於VM認爲文件應該寫入後備存儲(而不是交換空間),可是ramfs沒有任何後備存儲。
所以,只容許root(或可信用戶)對ramfs mount進行寫訪問。
其餘內核開發人員建立了一個名爲「tmpfs」的改進版本.tmpfs(之前稱爲shmfs)基於啓動時使用的ramfs代碼,,但與ramfs不一樣,它支持交換較少使用的頁面以交換空間以及文件系統大小和inode限制以防止內存不足的狀況(默認爲物理RAM的一半和RAM頁面的一半)。
(它能夠將數據寫入交換空間,並限制給定掛載點的大小,避免填滿全部可用的內存)。Initramfs是tmpfs的一個實例。
能夠容許普通用戶對tmpfs掛載進行寫訪問。這些基於ram的文件系統會自動增加或縮小以適應它們包含的數據大小。物盡其用,不會浪費額外的空間,不須要模擬塊設備操做的額外開銷。
2.3 ramdisk vs ramfs
2.4及更早版本使用 | 2.6以上版本 |
ramdisk | ramfs > tmpfs |
initrd | initramfs |
基於ram的塊設備 | 基於ram的文件系統 |
固定大小的內存塊 | 會自動增加或縮小以適應包含的數據大小 |
資源浪費,模擬塊設備,額外的開銷 | 物盡其用 |
舊的initrd始終是一個單獨的文件 | 而initramfs存檔連接到linux內核映像 |
initrd文件是一個gzip壓縮的文件系統映像(在例如ext2,須要內置的驅動程序) | initramfs存檔是一個gzip壓縮的cpio存檔(好比tar更簡單) 內核的cpio提取代碼很是小,並且還能夠在啓動過程當中丟棄__init文本和數據。 |
舊的initrd(稱爲/initrd,而不是/init) 運行程序進行一些設置,而後返回到內核 |
而initramfs的init程序不會返回內核. 若是/init須要切換控制,它可使用新的根設備進行超載/執行另外一個init程序。 |
當切換另外一個根設備時,initrd將pivot_root,而後卸載ramdisk。 | initramfs是rootfs,既不能使用pivot_root rootfs,也沒法卸載。 而是刪除rootfs中的全部內容以釋放空間 (find -xdev / -exec rm '{}' ';'), 使用新根 (cd /newmount; mount --move . /; chroot .), 覆蓋rootfs。 將 stdin/stdout/stderr 附加到新的 /dev/console, 並執行新的init。 |
ramdisk,模擬塊設備,實例是initrd,前文描述的弊端,已不多使用。
tmpfs,臨時文件系統,是ramfs的改進版本,實例是目前主流的initramfs,初始ram文件系統。
2.4 臨時文件系統
2.4.1 觀察tmpfs
tmpfs是許多類Unix操做系統上臨時文件存儲設施的通用名稱。能夠經過df觀察到在某些Linux發行版(例如Debian,Ubuntu)上,/tmp是普通目錄,但/dev/shm使用tmpfs。
如下是arch linux環境
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
dev 4072256 0 4072256 0% /dev
run 4079692 864 4078828 1% /run
/dev/sdb6 31364968 14256088 15492548 48% /
/dev/sdb7 34422400 7942172 24708608 25% /home
tmpfs 4079692 416068 3663624 11% /dev/shm
tmpfs 4079692 0 4079692 0% /sys/fs/cgroup
tmpfs 4079692 32 4079660 1% /tmp
tmpfs 815936 24 815912 1% /run/user/1001
2.4.2 Initramfs
初始ram文件系統,也稱早期用戶空間,典型用途是檢測加載主用戶空間文件系統所需的設備驅動程序,並從臨時文件系統加載它們。initramfs只須要包含訪問根文件系統所需的模塊; 它不須要包含一我的們想要使用的每一個模塊。在init過程當中,udev將在稍後加載大多數模塊。
Arch Linux使用內置initramfs的空存檔(這是構建Linux時的默認存檔)。
第一個提取的initramfs是在內核構建期間嵌入在內核二進制文件中的initramfs,而後提取可能的外部initramfs文件。
所以,外部initramfs中的文件會覆蓋嵌入式initramfs中具備相同名稱的文件。而後內核執行/init(在rootfs中)做爲第一個進程。
2.4.3 查看initramfs
若是您對initramfs映像中的內容感到好奇,能夠將其解壓縮並查看其中的文件。initramfs映像是一個SVR4 CPIO歸檔文件,經過find和bsdcpio命令生成,可選擇使用內核理解的壓縮方案進行壓縮。
mkinitcpio包含一個名爲的實用程序lsinitcpio,它將列出和/或提取initramfs圖像的內容。
列出鏡像中的文件:
$ lsinitcpio /boot/initramfs-linux.img
當前目錄中提取:
$ lsinitcpio -x /boot/initramfs-linux.img
更加人性化的重要部分列表:
$ lsinitcpio -a /boot/initramfs-linux.img
2.4.4 建立initramfs
https://wiki.archlinux.org/index.php/Mkinitcpiomkinitcpio是一個用於建立初始ramdisk環境的Bash腳本。
默認狀況下,mkinitcpio腳本在內核安裝或升級後生成兩個鏡像:默認鏡像和跳過自動檢測掛鉤的回退鏡像,所以包含了大量不須要的模塊。
這是經過大多數內核包安裝的.preset文件的PRESETS指令來完成的(例如,對於linux包含)。
預設是如何建立initramfs鏡像的預約義定義,而不是每次都指定配置文件和輸出文件。
例如,如下將(從新)生成由...提供的預設/etc/mkinitcpio.d//etc/mkinitcpio.d/linux.presetPRESETS=('default' 'fallback')-p--presetlinux包:
# mkinitcpio -p linux
附加配置文件位於/etc/mkinitcpio.conf並用於指定全部預設的全局選項。
的-P/ --allpresets開關指定的全部預置應在後再生的initramfs時被利用mkinitcpio.conf的變化。
用戶可使用各類不一樣的配置建立任意數量的initramfs鏡像。必須在相應的引導加載程序配置文件中指定所需的鏡像。
警告: .preset文件用於在內核更新後自動從新生成initramfs; 編輯時要當心。
mkinitcpio的主要配置文件是/etc/mkinitcpio.conf。
另外,預設定義由/etc/mkinitcpio.d目錄中的內核包提供(例如/etc/mkinitcpio.d/linux.preset)。
生成自定義手動initcpio
用戶可使用備用配置文件生成鏡像。例如,如下內容將根據指示生成initramfs圖像/etc/mkinitcpio-custom.conf並將其保存/boot/linux-custom.img。
# mkinitcpio -c /etc/mkinitcpio-custom.conf -g /boot/linux-custom.img
若是爲當前正在運行的內核生成鏡像,請將內核版本添加到命令行。您能夠在中查看可用的內核版本/usr/lib/modules/。
# mkinitcpio -g /boot/linux-custom2.img -k 3.3.0-ARCH
用戶能夠修改配置文件中的六個變量:
MODULES 在運行任何引導掛鉤以前加載的內核模塊。
BINARIES 要包含在initramfs映像中的其餘二進制文件。
FILES 要包含在initramfs映像中的其餘文件。
HOOKS 掛鉤是在初始ramdisk中執行的腳本。
COMPRESSION 用於壓縮initramfs映像。
COMPRESSION_OPTIONS 傳遞給COMPRESSION程序的額外參數。強烈建議不要使用此設置。mkinitcpio將處理壓縮機的特殊要求(例如傳遞--check=crc32給xz),而且誤用很容易致使系統沒法啓動。
2.5 Linux系統中的initramfs
當前的Arch linux系統/boot/目錄下name | type | size |
vmlinuz-linux | DOS/Windows executable | 5.8Mb |
Initramfs-linux.img | Raw disk image | 8.7Mb |
Initramfs-linux-fallback.img | Raw disk image | 29.3Mb |
一些Linux的Live CD光盤文件裏
Linux | name | type | size |
manjaro | initramfs-x86_64.img | Raw disk image | 37Mb |
ubuntu18 | initrd | CPIO archive | 38Mb |
mint191 | initrd.lz initrd.lz 解壓後 initrd |
Lzip archive CPIO archive |
35Mb 153Mb |
2.6 cpio歸檔文件
https://en.wikipedia.org/wiki/Cpiocpio最初設計用於以連續,連續的方式在磁帶設備上存儲備份文件存檔。它不壓縮任何內容,可是一般使用gzip或其餘外部壓縮器壓縮生成的歸檔。
檔案建立
在使用-o命令行標誌啓動的複製操做期間建立存檔時,cpio從其標準輸入通道讀取文件和目錄路徑名,並將生成的存檔字節流寫入其標準輸出。
所以,Cpio一般與生成要歸檔的文件列表的其餘實用程序一塊兒使用,例如查找程序。
生成的cpio存檔是一系列文件和目錄,它們鏈接成一個存檔,由帶有文件元信息的標題部分分隔,例如文件名,inode編號,全部權,權限和時間戳。按照慣例,歸檔的文件名一般被賦予文件擴展名cpio。
此示例使用find實用程序生成從當前目錄開始的路徑名列表,以建立目錄樹的存檔:
$ find . -depth -print | cpio -o > /path/archive.cpio
提取
在由命令行標誌i啓動的拷入操做期間,cpio從其標準輸入讀取存檔,並在操做系統的文件系統中從新建立存檔文件。
命令行標誌d告訴cpio根據須要構造目錄。標誌v(詳細)列出提取時的文件名。
$ cpio -i -vd < archive.cpio
$ cpio -i -d /etc/fstab < archive.cpio
清單
列出cpio存檔中包含的文件:
$ cpio -t < archive.cpio
複製
此示例將從當前目錄開始的目錄樹複製到文件系統中的另外一個路徑new-path,
保留文件修改時間(標誌m),
根據須要建立目錄(d),
無條件地替換任何現有文件(u),
同時生成標準輸出的進度清單(v):
$ find . -depth -print | cpio -p -dumv new-path
3. 高級用戶
3.1 製做本身的initramfs
http://blog.falconindy.com/articles/optmizing-bootup-with-mkinitcpio.html使用mkinitcpio優化啓動
在最簡單的狀況下,掛載根分區須要如下驅動程序:
存儲總線(PATA,SATA,SCSI等)
塊設備
文件系統
lsinitcpio很高興地向你展現了圖像上的確切內容。
'mkinitcpio -M'將掃描您的PCI總線並探測您的根文件系統,返回一個整潔的模塊列表,沒有依賴項。
https://wiki.archlinux.org/index.php/Minimal_initramfs
最小的initramfs
3.2 Initramfs編程
https://landley.net/writing/rootfs-programming.html將一些可執行文件放入新的根文件系統。
使用mdev填充/dev
從rootfs切換到另外一個根文件系統
3.3 使用更新的工具
https://wiki.archlinux.org/index.php/Dracutdracut建立內核使用的初始映像,用於預加載訪問根文件系統所需的塊設備模塊(例如IDE,SCSI或RAID)。這可能會在不久的未來取代Arch Linux中的mkinitcpio。
https://dracut.wiki.kernel.org/index.php/Main_Page
注意:閱讀郵件列表公告,瞭解可能使用Dracut替換Mkinitcpio。
https://lists.archlinux.org/pipermail/arch-dev-public/2019-May/029570.html
[arch-dev-public] Mkinitcpio replacement with Dracut
Giancarlo Razzolini grazzolini at archlinux.org
Tue May 21 02:41:40 UTC 2019
Mkinitcpio替換爲Dracut的信息。有興趣有能力的人能夠多加關注,參與其中。
更多相關信息
https://landley.net/writing/rootfs-intro.html
https://wiki.debian.org/InitrdReplacementOptions
https://en.wikipedia.org/wiki/Initial_ramdisk
https://en.wikipedia.org/wiki/Tmpfs
https://en.wikipedia.org/wiki/Linux_startup_process
https://en.wikipedia.org/wiki/Initial_ramdisk
https://www.kernel.org/doc/Documentation/early-userspace/README 最後更新:2004-12-20
https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt 2005年10月17日
https://wiki.archlinux.org/index.php/Arch_boot_process#initramfs
https://wiki.archlinux.org/index.php/Mkinitcpio