精通initramfs构建step by stepWord格式.docx

上传人:b****6 文档编号:17441170 上传时间:2022-12-01 格式:DOCX 页数:26 大小:38.44KB
下载 相关 举报
精通initramfs构建step by stepWord格式.docx_第1页
第1页 / 共26页
精通initramfs构建step by stepWord格式.docx_第2页
第2页 / 共26页
精通initramfs构建step by stepWord格式.docx_第3页
第3页 / 共26页
精通initramfs构建step by stepWord格式.docx_第4页
第4页 / 共26页
精通initramfs构建step by stepWord格式.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

精通initramfs构建step by stepWord格式.docx

《精通initramfs构建step by stepWord格式.docx》由会员分享,可在线阅读,更多相关《精通initramfs构建step by stepWord格式.docx(26页珍藏版)》请在冰豆网上搜索。

精通initramfs构建step by stepWord格式.docx

(十一)klibc

截至到目前,我们都是基于busybox来构建initramfs。

还有一种广泛使用的initramfs构建方式是使用klibc软件包,包括一个小巧的C库和常用命令和工具。

Debian的initramfs构建工具就综合应用了busybox、udev、klibc。

(十二)大结局-测试一下

到现在为止,我们已经掌握了initramfs的构建方法,该到大结局了。

在大结局里,读者可应用前面step中介绍的方法,尝试分析一下Debian的initramfs,看看是否已精通了initramfs的构建方法。

一、initramfs是什么

在2.6版本的linux内核中,都包含一个压缩过的cpio格式的打包文件。

当内核启动时,会从这个打包文件中导出文件到内核的rootfs文件系统,然后内核检查rootfs中是否包含有init文件,如果有则执行它,作为PID为1的第一个进程。

这个init进程负责启动系统后续的工作,包括定位、挂载“真正的”根文件系统设备(如果有的话)。

如果内核没有在rootfs中找到init文件,则内核会按以前版本的方式定位、挂载根分区,然后执行/sbin/init程序完成系统的后续初始化工作。

这个压缩过的cpio格式的打包文件就是initramfs。

编译2.6版本的linux内核时,编译系统总会创建initramfs,然后把它与编译好的内核连接在一起。

内核源代码树中的usr目录就是专门用于构建内核中的initramfs的,其中的initramfs_data.cpio.gz文件就是initramfs。

缺省情况下,initramfs是空的,X86架构下的文件大小是134个字节。

二、构建第一个initramfs:

helloworld

从C语言开始,学习计算机编程语言的第一个程序几乎都是helloworld,因此我们也构建一个最简单的helloworld式的initramfs,以说明initramfs的基本构建方法。

initramfs的灵魂是init文件(或者叫程序,因为它会被内核第一个执行),我们先写一个简单的init程序,它会在内核的console中打印出经典的helloworld信息。

hello.c:

#include<

stdio.h>

unistd.h>

intmain(intargc,charargv[])

{

printf("

helloworld,frominitramfs.\n"

);

sleep(9999999);

return0;

}

其中的sleep()函数语句是为了避免执行时内核很快打出panic的信息,并非功能上的需要。

接着把hello.c编译成静态连接程序:

gcc-ohello_static-static-shello.c

命令行中的-s参数表示编译后的程序不包含调试定位信息,目的是减少编译出来的程序文件的大小。

再创建一个initramfs的构建源文件目录image,把hello_static程序拷入这个目录,并改名为init。

在image目录下,创建一个dev/console的设备文件,否init程序无法在内核console中输出信息:

mknod-m600dev/consolec51

注意,执行这个命令需要有root权限。

好了,现在可以设置内核配置参数,进行initramfs的构建了:

在generalsetup配置目录下的initramfssources配置项下输入image的路径名,比如我的路径就是/home/wyk/initramfs-test/image。

因为我们的init程序是ELF格式的,所以内核需要支持ELF的可执行文件,否则启动这个init程序会失败。

在内核的Executablefileformats配置目录下,选择kernelsupportforELFbinaries,则可使内核支持ELF格式的可执行文件。

其他内核配置参数根据实际需要设置即可,不过,为了减少内核编译时间,可参考这篇文章

内核配置参数设置完成后,按常规的内核编译方法进行编译,initramfs就自动连接到编译好的内核映像文件中了。

三、试验环境搭建

试验initramfs需要经常重启系统,所以使用CPU模拟器是不错的选择。

我们可以选用qemu,它支持直接启动linux内核,无需在模拟器中安装OS。

从方便使用的角度考虑,我们采用qemulauncher设置qemu的各项参数,它的安装可参考

在qemulauncher的linux配置标签中,打勾直接启动linux,然后在下面的文本框中填上刚才编译好的内核映像文件的路径名。

因为qemu的运行还需要设置硬盘映像文件,所以还需要在左边的配置标签中新建一个硬盘映像文件,但实际上我们并不使用硬盘。

配置好qemu的参数后,点击launcher按钮,内核就开始在qemu中运行了。

内核输出一堆内核运行信息后,最后打出了

helloworld,frominitramfs.

哈哈,我们构建的initramfs已经能够正常工作了!

四、什么是rootfs和ramfs

所有的2.6版本linux内核都有一个特殊的文件系统rootfs,是内核启动的初始始根文件系统,initramfs的文件会复制到rootfs。

如果把initramfs比作种子,那么rootfs就是它生长的土壤。

大部分linux系统正常运行后都会安装另外的文件系统,然后忽略rootfs。

rootfs是ramfs文件系统的一个特殊实例。

ramfs是一种非常简单的文件系统,是基于内存的文件系统。

ramfs文件系统没有容量大小的限制,它可以根据需要动态增加容量。

ramfs直接利用了内核的磁盘高速缓存机制。

所有的文件的读写数据都会在内存中做高速缓存(cache),当系统再次使用文件数据时,可以直接从内存中读写,以提供系统的I/O性能。

高速缓存中的写入数据会在适当的时候回写到对应的文件系统设备(如磁盘等)中,这时它的状态就标识为clean,这样系统在必要时可以释放掉这些内存。

ramfs没有对应文件系统设备,所以它的数据永远都不会回写回去,也就不会标识为clean,因此系统也永远不会释放ramfs所占用的内存。

因为ramfs直接使用了内核已有的磁盘高速缓存机制,所以它的实现代码非常小。

也由于这个原因,ramfs特性不能通过内核配置参数删除,它是内核的天然特性。

五、ramfs不是ramdisk

ramdisk是在一块内存区域中创建的块设备,用于存放文件系统。

ramdisk的容量是固定的,不能象ramfs一样动态增长。

ramdisk需要内核的文件系统驱动程序(如ext2)来操作其上的数据,而ramfs则是内核的天然特性,无需额外的驱动程序。

ramdisk也象其他文件系统设备一样,需要在块设备和内存中的磁盘高速缓存之间复制数据,而这种数据复制实际不必要的。

六、从ramfs派生的文件系统tmpfs

ramfs的一个缺点是它可能不停的动态增长直到耗尽系统的全部内存,所以只有root或授权用户允许使用ramfs。

为了解决这个问题,从ramfs派生出了tmpfs文件系统,增加了容量大小的限制,而且允许把数据写入交换分区。

由于增加了这两个特性,所以tmpfs允许普通用户使用。

关于tmpfs文件系统更多的信息,可以看内核源码中的Documentation/filesystems/tmpfs.txt文档。

综上所述,initramfs是一种ramfs文件系统,在内核启动完成后把它复制到rootfs中,作为内核初始的根文件系统,它的任务是挂载系统真正的根文件系统。

这就是initramfs的前世今生。

七、什么是busybox

busybox号称是嵌入式Linux中的瑞士军刀——小巧、功能齐全。

它把许多常用的Linux命令都集成到一个单一的可执行程序中,只用这一个可执行程序(即busybox)加上Linux内核就可以构建一个基本的Linux系统。

busybox程序非常小巧,包含全部命令可执行文件大小也只有750多K。

busybox是完全模块化的,可以很容易地在编译时增加、删除其中包含的命令。

由于busybox的这些特点,它广泛应用于LiveCD、应急修复盘、安装盘等系统中。

我们也是以它为基础,构建initramfs。

八、busybox的配置、编译和安装

(1)去去下载最新的源码,解压展开。

(2)用

makemenuconfig

命令启动配置界面配置,配置busybox的特性、选择要包含在busybox的命令(busybox称为applet);

也可以用

makedefconfig

命令做缺省配置,包含全部的applet。

另外两个配置命令是

makeallyesconfig——最大配置

makeallnoconfig——最小配置

它们和makedefconfig命令都可以用来作为自定义配置的初始配置,然后再用makemenuconfing命令做定制化配置。

为了简单,我们用makedefconfig做缺省配置。

(3)用

make

命令编译busybox软件。

(4)用

makeCONFIG_PREFIX=<

安装目录>

install

命令安装。

如果在命令行中省略CONFIG_PREFIX变量的赋值,则会安装缺省值./_install目录下。

CONFIG_PREFIX可以在makemenuconfig的配置界面中修改。

我们用makeCONFIG_PREFIX=~/initramfs-test/image命令把busybox安装到initramfs的构建目录中。

(5)缺省配置下,busybox动态链接到glibc,所以要把它用到的动态库复制到initramfs的构建目录中。

用ldd命令查看busybox用到了哪些动态库文件及相应的文件路径,然后把它们复制到相应的目录下即可。

我们编译的busybox需要向image/lib目录下复制

ld-linux.so.2

libc.so.6

libcrypt.so.1

libm.so.6

动态库文件。

九、在image下创建必要的目录和设备文件

(1)在imgae目录下创建

proc,sys,etc,mnt

四个目录

(2)helloworld已经创建了console设备文件,我们再用

mknod-m600dev/nullc13

命令创建另一个基本的设备文件。

十、试验一下

busybox的构建和准备工作做完了,我们试验一下吧:

在image目录下以root用户权限——

(1)用

mount-vtprocproc=proc

mount-vtsysfssysfs=sys

命令安装内核虚拟文件系统

mount-v-obind/devdev

命令绑定/dev的设备文件到image/dev

chroot./bin/sh

命令进入busybox的环境。

出现shell的命令提示符,可以试着输入几个命令,看看执行结果。

例如,输入fdisk-l命令看看是否能显示硬盘的分区。

十一、自动生成/dev下的设备文件

上节用chroot方法试验busybox时,为了简单,是用“绑定”的方式把主机的/dev中的设备文件映射到image目录下的dev目录。

在initramfs上,这种方法显然不能使用。

生成系统的设备文件,现在通常都是用udev动态生成,而initramfs为了做到通用,动态生成的要求是必须的。

在busybox中有一个mdev命令,就是用来动态生成设备文件,填充到/dev目录的。

在系统启动时,用

mdev-s

命令可以根据内核的sysfs文件系统在/dev目录中自动生成相应的设备文件。

命令执行前,需要先挂载内核的proc和sysfs虚拟文件系统。

十二、初始身手

解决了自动生成设备文件的问题后,我们可以试着做一个最简单的可运行的linux系统了:

(1)在image目录下写一个最简单的init脚本。

#!

/bin/sh

mount-tprocproc/proc

mount-tsysfssysfs/sys

(2)为init脚本设置可执行权限,否则内核不会去执行它。

chmod+xinit

(3)有些busybox配置中,mdev命令需要读取/etc/mdev.conf文件,为了避免出错信息,我们创建一个空文件。

mdev.conf文件是用来控制mdev生成的设备文件的读写权限的,在这里我们不需要对设备文件设置特别的权限,就使用mdev缺省的660的权限设置。

有关mdev的设备文件权限的控制详细信息,可参考busybox源码树docs目录下的mdev.txt文件。

touchetc/mdev.conf

(4)在内核源码目录下,执行

命令,重新编译内核,生成新的initramfs。

好了,在QEMU模拟环境下启动这个新的内核,系统初始化后,会进入SHELL环境。

在这个SHELL环境下,试验一些常用命令,看看是否可以正常运行。

十三、can'

taccesstty

上一步创建的简单linux系统在进入SHELL环境时,会打出下面这一句出错信息:

/bin/sh:

can'

taccesstty;

jobcontrolloff

虽然不影响使用,但终究不够完美。

产生这个错误的原因是我们的SHELL是直接运行在内核的console上的,而console是不能提供控制终端(terminal)功能的,所以必须把SHELL运行在tty设备上,才能消除这个错误。

解决问题的办法是使用正规init机制,在执行SHELL前打开tty设备。

另外,这个简单系统的reboot、halt等命令是不起作用的,也必须通过init方式解决。

十四、busybox的缺省init模式

busybox支持init功能,当系统没有/etc/inittab文件时,它有一套缺省的模式,按下面配置执行:

:

sysinit:

/etc/init.d/rcS

askfirst:

ctrlaltdel:

/sbin/reboot

shutdown:

/sbin/swapoff-a

/bin/umount-a-r

restart:

/sbin/init

如果busybox检测到/dev/console不是串口控制台,init还要执行下面的动作:

tty2:

tty3:

tty4:

我们试试这种模式是否可以解决我们的问题。

(1)写/etc/init.d/rcS脚本

这个脚本实际是要执行系统的初始化操作。

我们把前面的init脚本改造一下,将最后的/bin/sh命令删除,然后移到etc/init.d目录下,改名为rcS。

(2)initramfs不需要linuxrc,而且如果没有init文件,内核就不认为它是一个有效的initramfs,因而不安装它,导致内核panic。

于是,我们在image目录下,把busybox安装的linuxrc改名为init:

mvlinuxrcinit

(3)重新编译内核,生成新的initramfs

(4)用QEMU试验一下新编译的内核。

系统启动后,会打出一句话“pleasepressEntertoactivethisconsole”——感觉还不错。

但是按下回车键后,系统依然会打出错误信息“-/bin/sh:

can'

jobcontrolloff”。

用tty命令看看当前的终端设备文件名:

#tty

/dev/console

它还是console,不是tty设备,所以问题没有解决。

不过,reboot和halt命令倒是可以正常工作了。

经过验证,busybox的缺省init模式无法满足我们的要求,我们还是要写inittab,定制自己的init初始化流程。

十五、busybox的inittab文件格式说明

要写自己的inittab,需要理解busybox的inittab文件格式。

busybox的inittab文件与通常的inittab不同,它没有runlevel的概念,语句功能上也有限制。

inittab语句的标准格式是

<

id>

runlevels>

action>

process>

各字段的含义如下

id字段与通常的inittab中的含义不同,它代表的是这个语句中process执行所在的tty设备,内容就是/dev目录中tty设备的文件名。

由于是运行process的tty设备的文件名,所以也不能象通常的inittab那样要求每条语句id的值唯一。

busybox不支持runlevel,所以此字段完全被忽略。

为下列这些值之一:

sysinit,respawn,askfirst,wait,once,restart,ctrlaltdel,shutdown

其含义与通常的inittab的定义相同。

特别提一下askfirst,它的含义与respawn相同,只是在运行process前,会打出一句话“pleasepressEntertoactivethisconsole”,然后等用户在终端上敲入回车键后才运行process。

指定要运行的process的命令行。

十六、写minilinux的inittab

理解了busybox的inittab格式,我们就可以写minilinux的inittab:

tty1:

tty5:

tty6:

把这个文件放到image的etc目录下。

为了执行reboot命令时避免提示找不到/etc/fstab文件,我们再在etc目录下创建一个空文件:

touchfstab

做好了这些,就可以重新编译内核,生成新的initramfs了。

在QEMU试验环境下验证新生成的minilinux,系统运行正常,而且象通常的linux系统一样,用ALT+F1~F6键可以在6个终端间切换。

由于minilinux系统不需要登录,所以用askfirst的方式来模拟登录,用户敲回车键后,init进程才会启动shell。

十七、配置内核支持initrd

到目前为止,我们的initramfs都由内核编译系统生成的,并链接到内核中。

首先配置内核使用单独的initrd:

在DeviceDriver/Blockdevice/配置目录下,选择RAMfilesystemandRAMdisk(initramfs/initrd)support配置项;

再到GeneralSetup配置目录项下,将initramfssourcefile(s)配置项原有的内容清空。

然后把内核源码树的usr目录下已由内核编译生成的initramfs文件initramfs_data.cpio.gz拷贝到~/initramfs-test目录下,我们先直接用这个文件试验一下initrd方式的initramfs的效果。

最后,执行make命令重新编译内核后,在QEMU试验环境中,把initrd配置框(linux

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 信息与通信

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1