今天為大家介紹的是制作unix啟動(dòng)盤圖文教程,系統(tǒng)奔潰是很多的用戶會(huì)遇到的問題,也是大家不愿意看到的,這是使用做unix啟動(dòng)盤可以幫大家解決這些問題,今天為大家介紹制作unix啟動(dòng)盤圖文教程是希望大家可以更好的解決系統(tǒng)奔潰的現(xiàn)象。
一、制作一個(gè)顯示hello world的啟動(dòng)linux
一、 initramfs 是什么
當(dāng)內(nèi)核啟動(dòng)時(shí),會(huì)從這個(gè)打包文件中導(dǎo)出文件到內(nèi)核的 rootfs 文件系統(tǒng),然后內(nèi)核檢查 rootfs 中是否包含有 init 文件,如果有則執(zhí)行 它,作為 PID 為 1 的第一個(gè)進(jìn)程。這個(gè) init 進(jìn)程負(fù)責(zé)啟動(dòng)系統(tǒng)后續(xù)的工作,包括定位、掛載“真正的”根文件系統(tǒng)設(shè)備(如果有的話)。如果內(nèi)核沒有在 rootfs 中找到 init 文件,則內(nèi)核會(huì)按以前版本的方式定位、掛載根分區(qū),然后執(zhí)行/sbin/init 程序完成系統(tǒng)的后續(xù)初始化工作。
二、構(gòu)建第一個(gè) initramfs : hello world
從 C 語(yǔ)言開始,學(xué)習(xí)計(jì)算機(jī)編程語(yǔ)言的第一個(gè)程序幾乎都是 hello world,因此我們也構(gòu)建一個(gè)最簡(jiǎn)單 的 hello world 式的 initramfs,以說明 initramfs 的基本構(gòu)建方法。 initramfs 的靈魂是 init 文件(或者叫程序,因?yàn)樗鼤?huì)被內(nèi)核第一個(gè)執(zhí)行),我們先寫一個(gè)簡(jiǎn)單的 init 程序,它會(huì)在內(nèi)核的 console 中打印出經(jīng)典的 hello world 信息。
hello.c:
#include
#include
int main(int argc,char argv[])
{
printf("hello world, from initramfs./n");
sleep(9999999);
return 0;
}
其中的 sleep()函數(shù)語(yǔ)句是為了避免執(zhí)行時(shí)內(nèi)核很快打出 panic 的信息,并非功能上的需要。
接著把 hello.c 編譯成靜態(tài)連接程序:
gcc -o hello_static -static -s hello.c
命令行中的-s 參數(shù)表示編譯后的程序不包含調(diào)試定位信息,目的是減少編譯出來(lái)的程序文件的大小。
再創(chuàng)建一個(gè) initramfs 的構(gòu)建源文件目錄 image,把 hello_static 程序拷入這個(gè)目錄,并改名為
init。
在 image 目錄下,創(chuàng)建一個(gè) dev/console 的設(shè)備文件,否 init 程序無(wú)法在內(nèi)核 console 中輸出信息:
mknod -m 600 dev/console c 5 1
注意,執(zhí)行這個(gè)命令需要有 root 權(quán)限。
我的練習(xí)目錄是這樣的/home/fjb/home/test/initramfs/t1。我在t1目錄下建立了image目錄。其中sudo mkdo -m 600 dev/console c 5 1 這個(gè)命令是創(chuàng)建一個(gè)設(shè)備文件,-m mode, --mode=mode 為新建立的文件設(shè)定模式,就象應(yīng)用命令chmod一樣,以后仍然使用缺省模式建立新目錄。 dev/console是要?jiǎng)?chuàng)建的設(shè)備,即一個(gè)控制臺(tái)設(shè)備,我們后面在啟動(dòng)linux時(shí)其顯示的信息會(huì)用上這個(gè)控制臺(tái),我們可以在image目錄下先建立dev目錄(mkdir dev),c表示是字符設(shè)備,5和1是主次版本號(hào)。注意在ubuntu上要用超級(jí)用戶權(quán)限才可以建立。
這樣在t1目錄下就有了hello.c、hello_static文件和image目錄,在image目錄里有init文件和dev目錄,在dev目錄下有console設(shè)備文件。
好,現(xiàn)在可以構(gòu)建initramfs了。
首先是配置linux。我把linux-2.6.31.tar.bz2拷貝到/home/fjb/test/initramfs/目錄下,運(yùn)行tar -xvf linux-2.6.31.tar.bz2進(jìn)行解壓,在initramfs目錄下生成一個(gè)linux-2.6.31目錄,里面有l(wèi)inux的源代碼(linux的下載可以在https://kernel.org/pub/linux/kernel/ 的2.6目錄里下載)。
進(jìn)入linux-2.6.31目錄,運(yùn)行make menuconfig,會(huì)出現(xiàn)如下圖的配置畫面:
在general setup的配置目錄下的選上Initial RAM filesystem and RAM disk (initramfs/initrd) support選項(xiàng),選上的話,旁邊的中括號(hào)會(huì)有個(gè)*,然后在下面輸入/home/fjb/home/test/initramfs/t1/image,如下圖:
因?yàn)槲覀兊?init 程 序是 ELF 格式的,所以內(nèi)核需要支持ELF 的可執(zhí)行文件,否則啟動(dòng)這個(gè) init 程序會(huì)失敗。在內(nèi)核的 Executable file formats 配置目錄下,選擇 kernel support for ELF binaries,則可使內(nèi)核支持 ELF 格式的可執(zhí)行文件。其他內(nèi)核 配置參數(shù)根據(jù)實(shí)際需要設(shè)置即可,不過,為了減少內(nèi)核編譯時(shí)間,可參考這篇文章
三、適合CLFS臨時(shí)系統(tǒng)的最簡(jiǎn)內(nèi)核配置
我的host系統(tǒng)是32位的,無(wú)法使用chroot方式構(gòu)建CLFS系統(tǒng),只能先交叉編譯出一個(gè)最小的臨時(shí)系統(tǒng),然后以BOOT方式完成CLFS系統(tǒng)的構(gòu)建。在CLFS BOOK中,對(duì)臨時(shí)系統(tǒng)的內(nèi)核的配置有下面的警告:
Warning
Here a temporary cross-compiled kernel will be built. When configuring it, select the minimal amount of options required to boot the target machine and build the final system. I.e., no support for sound, printers, etc. will be needed.
Also, try to avoid the use of modules if possible, and don't use the resulting kernel image for production systems.
那么,怎樣得到一個(gè)適合CLFS臨時(shí)系統(tǒng)的最簡(jiǎn)內(nèi)核配置呢?
(1)首先,用內(nèi)核的 allnoconfig 配置目標(biāo),得到一個(gè)最最基本的內(nèi)核配置。即,執(zhí)行下面的命令:
make ARCH=x86_64 CROSS_COMPILE=${CLFS_TARGET}- allnoconfig
內(nèi)核的 allnoconfig 配置目標(biāo)會(huì)把所有的內(nèi)核選項(xiàng)都設(shè)置為no,也就是把它們既不編譯進(jìn)內(nèi)核,也不編譯成模塊。有了這個(gè)最基本的配置,我們?cè)偬砑覥LFS臨時(shí)系統(tǒng)所必須的配置項(xiàng):再執(zhí)行
make ARCH=x86_64 CROSS_COMPILE=${CLFS_TARGET}- menuconfig
命令,按下面的步驟添加其他的配置——
(2)按CLFS BOOK的建議,把 Executable file formats 下的ELF 和 emulations for 32bit ELF 選項(xiàng)編譯進(jìn)內(nèi)核。
(3)在 Processor type and features 下面,選擇合適的CPU類型。例如,我的CPU類型是Intel EM64T
(4)選擇PCI/PCI-Express支持,位于Bus options (PCI, PCMCIA, EISA, MCA, ISA) 配置目錄下。
(5)加入對(duì)根文件系統(tǒng)所在磁盤控制器的驅(qū)動(dòng),詳細(xì)方法可參考:https://linuxman.blog.ccidnet.com/blog-htm-do-showone-uid-60710-type-blog-itemid-280649.html。例如,我的機(jī)器的配置是:
Device Driver
|---->SCSI device support
|---->SCSI disk support
|----->SCSI low-level drivers
|---->Serial ATA (SATA) support
|---->intel PIIX/ICH SATA support
(6)加入Ext2文件系統(tǒng)的支持:在 File systems 配置目錄下,選擇 Second extended fs support。如果根文件系統(tǒng)是Ext3,則選擇 Ext3 journalling file system support。
(7)為了是 Udev 正常工作,需要內(nèi)核支持 Unix domain sockets。此配置選項(xiàng)位于 Networking 配置目錄中的 Networking support ---> Networking options 下。
(8) 使內(nèi)核支持 /proc 虛擬文件系統(tǒng)和 tmpfs 文件系統(tǒng): File systems ---> Pseudo filesystems ---> /proc file system support / Virtual memory file system support (former shm fs)
(9)支持 swap 分區(qū): General setup ---> Support for paging of anonymous memory (swap)
(10)支持 RTC 設(shè)備: Device Drivers ---> Character devices ---> Enhanced Real Time Clock Support
(11) 為了充分發(fā)揮我的雙核CPU的能力,我又加入了對(duì)SMP的支持: Processor type and features ---> Symmetric multi-processing support。這一特性,對(duì)CLFS系統(tǒng)來(lái)說,并不是必須的。
這樣一個(gè)最簡(jiǎn)的內(nèi)核配置,編譯出來(lái)的內(nèi)核映像文件的大小只有744KB,但卻能完全滿足CLFS系統(tǒng)后續(xù)的構(gòu)建工作需要。
由于我的31內(nèi)核配置和他的有些不一樣,我就把sata和ata硬盤等的選項(xiàng)都選上了,(第一次制作,還不清楚很多選項(xiàng),沒辦法了)。
之后我們就可以保存選項(xiàng),然后運(yùn)行make bzImage之后在運(yùn)行make就ok了(編譯比較長(zhǎng)時(shí)間,慢慢等吧,我沒有咖啡泡,只能跑去吃飯了)。
二、實(shí)驗(yàn)環(huán)境的搭建
試驗(yàn) initramfs 需要經(jīng)常重啟系統(tǒng),所以使用 CPU 模擬器是不錯(cuò)的選擇。我們可以選用 qemu,它支持直接啟動(dòng) linux 內(nèi)核,無(wú)需在模擬器中安裝 OS。
如果在在命令行上用qemu的話會(huì)有問題,那是qemu的一個(gè)bug,對(duì)于27后的內(nèi)核支持不好,在運(yùn)行后會(huì)出現(xiàn)apic的錯(cuò)誤,如果要用命令行上用qemu的話,運(yùn)行qemu -kernel linux-2.6.31/arch/i386/boot/bzImage -append noapic -hda /dev/zero可以禁止內(nèi)核的apic。這樣就不會(huì)有這個(gè)問題。但這里有個(gè)更好的方法是用Qemu Luancher,既簡(jiǎn)單又方便好用。
在Linux系統(tǒng)下安裝圖形化的QEMU
QEMU是一款經(jīng)典的CPU模擬器軟件,但它是命令行方式程序,參數(shù)眾多,使用起來(lái)不是很方便。QEMU有一個(gè)圖形化的前端程序qemu-laucher,可方便地設(shè)置QEMU的命令行參數(shù)。
我的系統(tǒng)是Debian 4.0 Amd64,軟件庫(kù)中已包含了qemu-laucher,可以方便地安裝。安裝完整的圖形化QEMU環(huán)境,需要安裝下面的軟件包:
qemu:QEMU主程序
qemu-launcher:圖形化的QEMU啟動(dòng)器
kqemu-common:QEMU的加速模塊程序
qemuctl:QEMU的運(yùn)行時(shí)選項(xiàng)的設(shè)置程序,可作為qemu-laucher 的插件程序。
安裝完成后,在 Application/Accessories 系統(tǒng)菜單下,添加了qemu-laucher 的啟動(dòng)項(xiàng)。
我還有一個(gè)openSuse 10.3 的系統(tǒng),遺憾的是,它的軟件庫(kù)中沒有包含qemu-laucher,無(wú)法直接安裝。
ubuntu就方便了,在新立得里就可以把這些全裝上了。裝完后會(huì)生成一個(gè)菜單:應(yīng)用程序-》附件-》Qemu Launcher。點(diǎn)擊一個(gè)菜單啟動(dòng) Qemu Launcher,如下圖。
其中,由于我們?cè)趩?dòng)linux時(shí)需要硬盤,雖然我們不是必須,但為了啟動(dòng)不出錯(cuò),我們可以New一個(gè)disk出來(lái),如上圖的Hand disk 0,我建了一個(gè)100M的虛擬硬盤t1。
然后點(diǎn)擊linux boot選項(xiàng),勾上Boot Linux kernel directly選項(xiàng),在下面的Kernel image中找到我們剛才生成的bzImage文件,在 linux-2.6.31/arch/i386/boot/bzImage文件夾里。在Initial RAM disk選擇中選擇我們剛才生成的那個(gè)硬盤。好了,到此我們已可以啟動(dòng)我們剛才建立的linux了,點(diǎn)擊Launch可以運(yùn)行我們的linux了(記得點(diǎn)擊Save按鈕,不然下次啟動(dòng)Qemu Launcher時(shí)又的重新去找那些文件)。
內(nèi)核輸出一堆內(nèi)核運(yùn)行信息后,最后打出了 hello world, from initramfs。如下圖:
三、什么是initramfs
1.initramfs 的前世今生
1.1什么是 rootfs 和 ramfs 所有的 2.6 版本 linux 內(nèi)核都有一個(gè)特殊的文件系統(tǒng) rootfs,是內(nèi)核啟動(dòng)的初始始根文件系統(tǒng), initramfs 的文件會(huì)復(fù)制到 rootfs。如果把 initramfs 比作種子,那么 rootfs 就是 它生長(zhǎng)的土壤。大部分 linux 系統(tǒng)正常運(yùn)行后都會(huì)安裝另外的文件系統(tǒng),然后忽略 rootfs。rootfs 是 ramfs 文件系統(tǒng)的一個(gè)特殊實(shí)例。ramfs 是一種非常簡(jiǎn)單的文件系統(tǒng),是基于內(nèi)存的文件系統(tǒng)。ramfs 文件系統(tǒng)沒有容量大小的限制,它可以根據(jù)需要?jiǎng)討B(tài)增加容量。ramfs 直接利用了內(nèi)核的磁盤高速緩存機(jī)制。所有的文件的讀寫數(shù)據(jù)都會(huì)在內(nèi)存中做高速緩存(cache),當(dāng)系統(tǒng)再次使用文件數(shù)據(jù)時(shí),可以直接從內(nèi)存中讀寫,以提 供系統(tǒng)的 I/O 性能。高速緩存中的寫入數(shù)據(jù)會(huì)在適當(dāng)?shù)臅r(shí)候回寫到對(duì)應(yīng)的文件系統(tǒng)設(shè)備(如磁盤等)中,這時(shí)它的狀態(tài)就標(biāo)識(shí)為clean,這樣系統(tǒng)在必要時(shí)可 以釋放掉這些內(nèi)存。ramfs 沒有對(duì)應(yīng)文件系統(tǒng)設(shè)備,所以它的數(shù)據(jù)永遠(yuǎn)都不會(huì)回寫回去,也就不會(huì)標(biāo)識(shí)為 clean,因此系統(tǒng)也永遠(yuǎn)不會(huì)釋放 ramfs 所占 用的內(nèi)存。因?yàn)?ramfs 直接使用了內(nèi)核已有的磁盤高速緩存機(jī)制,所以它的實(shí)現(xiàn)代碼非常小。也由于這個(gè)原因, ramfs 特性不能通過內(nèi)核配置參數(shù)刪除,它是內(nèi)核的天然特性。
1.2ramfs 不是 ramdisk
ramdisk 是在一塊內(nèi)存區(qū)域中創(chuàng)建的塊設(shè)備,用于存放文件系統(tǒng)。ramdisk 的容量是固定的,不能象
ramfs 一樣動(dòng)態(tài)增長(zhǎng)。ramdisk 需要內(nèi)核的文件系統(tǒng)驅(qū) 動(dòng)程序(如 ext2)來(lái)操作其上的數(shù)據(jù),而ramfs 則是內(nèi)核的天然特性,無(wú)需額外的驅(qū)動(dòng)程序。ramdisk 也象其他文件系統(tǒng)設(shè)備一樣,需要在塊設(shè)
備和 內(nèi)存中的磁盤高速緩存之間復(fù)制數(shù)據(jù),而這種數(shù)據(jù)復(fù)制實(shí)際不必要的。
1.3從 ramfs 派生的文件系統(tǒng) tmpfs
ramfs 的一個(gè)缺點(diǎn)是它可能不停的動(dòng)態(tài)增長(zhǎng)直到耗盡系統(tǒng)的全部?jī)?nèi)存,所以只有 root 或授權(quán)用戶允許
使用 ramfs。為了解決這個(gè)問題,從 ramfs 派生出了 tmpfs 文件系統(tǒng),增加了容量大小的限制,而且允
許把數(shù)據(jù)寫入交換分區(qū)。由于增加了這兩個(gè)特性,所以 tmpfs 允許普通用戶使用。關(guān)于 tmpfs 文件系統(tǒng)更多的信息,可以看內(nèi)核源碼中的 Documentation/filesystems/tmpfs.txt 文檔。
綜上所述,initramfs 是一種 ramfs 文件系統(tǒng),在內(nèi)核啟動(dòng)完成后把它復(fù)制到 rootfs 中,作為內(nèi)核初始的根文件系統(tǒng),它的任務(wù)是掛載系統(tǒng)真正的根文件系統(tǒng)。這就是 initramfs 的前世今生。
四、使用busybox構(gòu)建
busybox 號(hào)稱是嵌入式 Linux 中的瑞士軍刀——小巧、功能齊 全。它把許多常用的 Linux 命令都集成到一個(gè)單一的可執(zhí)行程序中,只用這一個(gè)可執(zhí)行程序(即 busybox)加上 Linux 內(nèi)核就可以構(gòu)建一個(gè)基本的 Linux 系統(tǒng)。busybox 程序非常小巧,包含全部命令可執(zhí)行文件大小也只有 750 多。busybox 是完全模塊化的,可以很容易地在編譯時(shí)增加、 刪除其中包含的命令。
由于 busybox 的這些特點(diǎn),它廣泛應(yīng)用于 LiveCD、應(yīng)急修復(fù)盤、安裝盤等系統(tǒng)中。我們也是以它為基礎(chǔ),構(gòu)建 initramfs 。
4.1編譯busybox
我們可以去https://busybox.net 上下載最新的busybox源碼,我在上面下載的是最新的busybox-1.15.2.tar.bz2版本。把它解壓到initramfs目錄下,可以用make menuconfig進(jìn)行配置,另外兩個(gè)配置命令是
make allyesconfig——最大配置
make allnoconfig——最小配置
這里用 make defconfig 做缺省配置。
用make CONFIG_PREFIX=<安裝目錄> install 命令安裝。如果在命令行中省略 CONFIG_PREFIX 變量的賦值,則會(huì)安裝缺省值 ./_install 目錄下。CONFIG_PREFIX 可以在 make menuconfig 的配置界面中修改。
在busybox-1.15.2目錄下運(yùn)行
make defconfig
make CONFIG_PREFIX=/home/fjb/home/test/initramfs/t1/image install
那么我們就可以把busybox安裝在image目錄下了,image目錄下會(huì)多出幾個(gè)文件夾和文件,如下圖:
缺省配置下,busybox 動(dòng)態(tài)鏈接到 glibc,所以要把它用到的動(dòng)態(tài)庫(kù)復(fù)制到 initramfs 的構(gòu)建目錄中。用 ldd 命令查看 busybox 用到了哪些動(dòng)態(tài)庫(kù)文件及相應(yīng)的文件路徑,然后把它們復(fù)制到相應(yīng)的目錄下即可。
在image/bin 目錄下,我們運(yùn)行
ldd busybox
得到的結(jié)果如下:
linux-gate.so.1 => (0x00137000)
libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x009ce000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00138000)
/lib/ld-linux.so.2 (0x00f04000)
我們可以在image下建立lib目錄,把這幾個(gè)苦拷貝到lib目錄下。
這里要注意了,我在這里就浪費(fèi)了很多時(shí)間。
首先: linux-gate.so.1這個(gè)庫(kù)我們是找不到的,因?yàn)閘inux下根本沒有這個(gè)庫(kù),具體來(lái)說就google一下咯,上面有解釋,一句話,這個(gè)不需要。
libm.so.6、 libc.so.6和/ld-linux.so.2這三個(gè)其實(shí)在/lib目錄下,在/lib/tls/i686/cmov/下也有。他們都是鏈接文件,剛開始我用cp命令拷貝他們,拷貝他們的鏈接文件也可以順這鏈接找到原文件并拷貝過去,但在最后啟動(dòng)的時(shí)候老是提示/bin/sh: error while loading shared libraries: /libm.so.6: cannot open shared object file: No such file or directory
我在網(wǎng)上找了很久也沒找到答案,明明在在image/lib目錄下有這個(gè)庫(kù),為什么老是提示說找不到呢,最后沒辦法,只好老老實(shí)實(shí)的把libm.so.6、 libc.so.6和/ld-linux.so.2這三個(gè)庫(kù)所鏈接的文件ld-2.10.1.so、libc-2.10.1.so、libm-2.10.1.so拷貝到lib目錄下,然后建立這三個(gè)文件的鏈接文件:
ln -s ld-2.10.1.so ld-linux.so.2
ln -s libc-2.10.1.so libc.so.6
ln -s libm-2.10.1.so libm.so.6
這樣后,最后啟動(dòng)成功,具體什么原因我還沒去弄清楚,望知道的朋友告訴我,謝謝!
4.2在 image 下創(chuàng)建必要的目錄和設(shè)備文件
在image目錄下運(yùn)行
mkdir proc etc sys mnt
生成proc etc sys mnt這4個(gè)目錄。
hello world 已經(jīng)創(chuàng)建了 console 設(shè)備文件,我們?cè)儆?/p>
mknod -m 600 dev/null c 1 3
命令創(chuàng)建另一個(gè)基本的設(shè)備文件。
4.3制作一個(gè)最簡(jiǎn)單的linux系統(tǒng)
我們可以試著做一個(gè)最簡(jiǎn)單的可運(yùn)行的 linux 系統(tǒng)了:
首先刪除image目錄下的init文件,然后在image目錄下寫個(gè)init 的腳本,過程如下:
(1)在 image 目錄下寫一個(gè)最簡(jiǎn)單的 init 腳本。
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s
/bin/sh
(2)為 init 腳本設(shè)置可執(zhí)行權(quán)限,否則內(nèi)核不會(huì)去執(zhí)行它。
chmod +x init
(3)有些 busybox 配置中,mdev 命令需要讀取/etc/mdev.conf 文件,為了避免出錯(cuò)信息,我們創(chuàng)建一個(gè)空文件。
touch etc/mdev.conf
(4)在內(nèi)核源碼目錄下,執(zhí)行
make
命令,重新編譯內(nèi)核,生成新的 initramfs。
好了,在 QEMU 模擬環(huán)境下啟動(dòng)這個(gè)新的內(nèi)核,系統(tǒng)初始化后,會(huì)進(jìn)入 SHELL 環(huán)境。在這個(gè) SHELL 環(huán)境下,試驗(yàn)一些常用命令,看看是否可以正常運(yùn)行。我的運(yùn)行如下圖所示:
上一步創(chuàng)建的簡(jiǎn)單 linux 系統(tǒng)在進(jìn)入 SHELL 環(huán)境時(shí),會(huì)打出下面這一句出錯(cuò)信息:
/bin/sh: can't access tty; job controll off
雖然不影響使用,但終究不夠完美。產(chǎn) 生這個(gè)錯(cuò)誤的原因是我們的 SHELL 是直接運(yùn)行在內(nèi)核的 console 上的,而 console 是不能提供控制終端(terminal)功能的,所以必須把 SHELL 運(yùn)行在 tty 設(shè)備上,才能消除這個(gè)錯(cuò)誤。解決問題的辦法是使用正規(guī) init 機(jī)制,在執(zhí)行 SHELL 前打開 tty 設(shè)備。
另外,這個(gè)簡(jiǎn)單系統(tǒng)的 reboot、halt 等命令是不起作用的,也必須通過 init 方式解決。
我們可以嘗試在這個(gè)linux下運(yùn)行tty這個(gè)命令,它打印出/dev/console,這說明它是運(yùn)行在console上的。
4.4 busybox 的缺省 init 模式
busybox 支持 init 功能,當(dāng)系統(tǒng)沒有/etc/inittab 文件時(shí),它有一套缺省的模式,按下面配置執(zhí)行:
::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init
如果 busybox 檢測(cè)到/dev/console 不是串口控制臺(tái),init 還要執(zhí)行下面的動(dòng)作:
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
tty4::askfirst:/bin/sh
我們?cè)囋囘@種模式是否可以解決我們的問題。
說明一下,上面說的/etc/inittab是image/etc/inittab文件。并且是busybox工作。好了,我們開始下一個(gè)實(shí)驗(yàn)。將init腳本后面的/bin/sh那行刪除,并在etc目錄下建立init.d目錄,再把init文件移到etc/init.d目錄下更名為rcS
mv init etc/init.d/rcS
重新編譯內(nèi)核,生成新的 initramfs
用 QEMU 試驗(yàn)一下新編譯的內(nèi)核。我的Qemu運(yùn)行如下圖:
系統(tǒng)啟動(dòng)后,會(huì)打出一句話“please press Enter to active this console”——感覺還不錯(cuò)。但是按下回車鍵后,系統(tǒng)依然會(huì)打出錯(cuò)誤信息“-/bin/sh:
can't access tty; job controll off ”。用 tty 命令看看當(dāng)前的終端設(shè)備文件名:
# tty
/dev/console
它還是 console,不是 tty 設(shè)備,所以問題沒有解決。不過,reboot 和 halt 命令倒是可以正常工作了。
經(jīng)過驗(yàn)證,busybox 的缺省 init 模式無(wú)法滿足我們的要求,我們還是要寫 inittab,定制自己的 init 初始化流程。
4.5 busybox 的 inittab 文件格式說明
要寫自己的 inittab,需要理解 busybox 的 inittab 文件格式。
busybox 的 inittab 文件與通常的 inittab 不同,它沒有 runlevel 的概念,語(yǔ)句功能上也有限制。 inittab 語(yǔ)句的標(biāo)準(zhǔn)格式是
:::
各字段的含義如下
:
id 字段與通常的 inittab 中的含義不同,它代表的是這個(gè)語(yǔ)句中 process 執(zhí)行所在的 tty 設(shè)備,內(nèi)容就是/dev 目錄中 tty 設(shè)備的文件名。由于是運(yùn)行 process 的 tty 設(shè)備的文件名,所以也不能象通常的inittab 那樣要求每條語(yǔ)句 id 的值唯一。
:
busybox 不支持 runlevel,所以此字段完全被忽略。
:
為下列這些值之一:
sysinit, respawn, askfirst, wait,once, restart, ctrlaltdel, shutdown
其 含義與通常的 inittab 的定義相同。特別提一下 askfirst,它的含義與 respawn 相同,只是在運(yùn)
行 process 前,會(huì)打出一句話 “please press Enter to active this console”,然后等用戶在
終端上敲入回車鍵后才運(yùn)行 process。
:
指定要運(yùn)行的 process 的命令行。
4.6編寫inittab
理解了 busybox 的 inittab 格式,我們就可以寫 mini linux 的 inittab:
::sysinit:/etc/init.d/rcS
tty1::askfirst:/bin/sh
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
tty4::askfirst:/bin/sh
tty5::askfirst:/bin/sh
tty6::askfirst:/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
把這個(gè)文件放到 image 的 etc 目錄下。為了執(zhí)行 reboot 命令時(shí)避免提示找不到/etc/fstab 文件,我們?cè)僭?etc 目錄下創(chuàng)建一個(gè)空文件
touch fstab
在image/etc目錄下建立inittab文件,并將上面的內(nèi)容寫入這個(gè)文件。那么etc里的文件內(nèi)容就如下了:fstab init.d inittab
做好了這些,就可以重新編譯內(nèi)核,生成新的 initramfs 了。在 QEMU 試驗(yàn)環(huán)境下驗(yàn)證新生成的 linux,系統(tǒng)運(yùn)行正常,而且象通常的 linux 系統(tǒng)一樣,用 ALT+F1~F6 鍵可以在 6 個(gè)終端間切換。 注意:要在qemu里點(diǎn)擊鼠標(biāo)才可以用 ALT+F1~F6 鍵進(jìn)行終端間切換。要釋放鼠標(biāo),可以同時(shí)按住ctrl+alt并移動(dòng)鼠標(biāo)。
4.7配置內(nèi)核支持initrd
到目前為止,我們的 initramfs 都由內(nèi)核編譯系統(tǒng)生成的,并鏈接到內(nèi)核中。其實(shí)我們也可以用 cpio 命令生成單獨(dú)的 initramfs,與內(nèi)核編譯脫鉤,在內(nèi)核運(yùn)行時(shí)以 initrd 的形式加載到內(nèi)核,以增加靈活性。首 先配置內(nèi)核使用單獨(dú)的 initrd:在 Device Driver / Block device / 配置目錄下,選擇 RAM filesystem and RAMdisk ( initramfs/initrd ) support 配置項(xiàng);再到 General Setup 配置目錄項(xiàng)下,將 initramfs source file(s) 配置項(xiàng)原有的內(nèi)容清空。然后把內(nèi)核源碼樹的 usr 目錄下已由內(nèi)核編譯生成的 initramfs 文件 initramfs_data.cpio.gz 拷貝到 ~/initramfs-test 目錄下,我們先直接用這個(gè)文件試驗(yàn)一下 initrd 方式的 initramfs 的效果。最后,執(zhí)行 make 命令重新編譯內(nèi)核后,在 QEMU 試驗(yàn)環(huán)境中,把 initrd 配置框(linux 配置框的下面)的內(nèi)容 寫為
~/initramfs-test/initramfs_data.cpio.gz,指定 initrd 的文件路徑。
好了,試驗(yàn)一下新的 initrd 方式的 initramfs 吧,效果跟先前的完全一樣。
以下是我做的步驟,因?yàn)槲以诟鶕?jù)《精通initramfs構(gòu)建step by step》文后制作,由于里面說的不是很清楚,并且在Qemu Launch上的選項(xiàng)也沒有,所以花了比較多的時(shí)間,并且我也把其中一些沒有的步驟加上,多做實(shí)驗(yàn),多了解一下。
先做個(gè)實(shí)驗(yàn)。
到general setup中,RAM filesystem and RAMdisk ( initramfs/initrd ) support選項(xiàng)下的的Initramfs source file(s)的內(nèi)容清空。然后make,只好在啟動(dòng)Qemu Launch。
然后你會(huì)看到什么,我這里的啟動(dòng)后的界面如下圖:
以上便是制作unix啟動(dòng)盤圖文教程,由于我們沒有指定設(shè)備,所以啟動(dòng)到這里就沒了,可以參考啟動(dòng)上面的信息。并且我們生成的bzImage文件也小了很多。我這里只有1.2M,原來(lái)的要2.2M。
掃一掃 生活更美好