linux启动根文件系统

linux根文件系统启动方式

linux目前我所知道有3种启动文件系统的方式
1、从ramdisk根文件系统启动
这种方法需要

  1. 制作ramdisk文件系统压缩包
  2. 然后将这个文件压缩包通过bootloader下载到内存中
  3. 当系统启动的时候
    a) 通过uboot的bootargs环境变量来传递启动参数,修改为bootargs=initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64,以此指定从ramdisk启动,ramdisk压缩文件起始地址在内存地址0x31000000处,文件大小为0x200000。
    b) 或者不通过uboot传递启动参数,也可以通过修改内核配置Default kernel command string为”initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64”

2、文件系统已经存在于硬盘或者flash
kernel根据启动的命令行参数(root=/dev/xxx),直接进行mount。 这里有一个问题,在root文件系统本身还不存在的情况下,kernel如何根据/dev/xxx来找到对应的设备呢?注意:根文件系统和其他文件系统的mount方式是不一样的,kernel通过直接解析设备的名称来获得设备的主、从设备号,然后就可以访问对应的设备驱动了。所以在init/main.c中有很长一串的root_dev_names(如hda,hdab,sda,sdb,nfs,ram,mtdblock……),通过这个表就可以根据设备名称得到设备号。注意,bootloader或内核中设定的启动参数(root=/dev/xxx)只是一个代号,实际的根文件系统中不一定存在这个设备文件!

3、通过initramfs将根目录直接编译到linux内核镜像中
这种方法不同于前面两种方法需要在uboot启动参数中指定ramdisk加载到内存的地址或者文件系统在flash中的分区,由于已经将根目录编译到linux的.init.ramfs段中了,所以启动的时候直接将linux内核镜像的.init.ramfs段的内容解压到系统的rootfs中。

方法1在前面已经有说明,从ramdisk根文件系统启动Linux
下面具体来说说方法3是如何实现的


initramfs文件系统制作

本小节参考自:http://blog.csdn.net/pengrui18/article/details/14389233
1、制作根目录
mkdir rootfs
cd rootfs
mkdir bin dev etc lib proc sbin sys usr mnt tmp var
mknod -m 666 /dev/console c 5 1
2、配置busybox
进入Busybox Setting->
build options->
[]“Build busybox as a static binary”//动态链接
Cross Compile prefix(arm-linux-)
Installation Option->
[]Don’t usr/usr//避免busybox安装至宿主系统的usr,目录下
Busybox Installation Prefix(/xxx/rootfs)//安装位置
其他选项默认
make & make install
将busybox生成的文件拷贝到rootfs根目录中,也要将交叉编译工具下的/lib目录下的库文件拷贝过去。
3、建立initramfs文件系统启动时所需文件init (initramfs文件系统启动时会在根文件系统中执行第一个init程序,它对uboot传过来的参数init=/linuxrc不予理睬,所以需要在制作的根文件系统里的根目录加入init程序,否则无法启动。init程序和linuxrc程序一样都是符号链接文件,它们都是指向/bin/busybox程序)
cd rootfs
mv linuxrc init
4、添加内核对initramfs文件系统支持
make menuconfig
General setup —>
[
] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(/xxx/rootfs) Initramfs source file(s) #输入根文件系统的所在目录
另外initramfs source files除了可以指定根目录还可以指定一个或者多个romfs.txt文件,文件的内容大概如下:
dir /dev 755 0 0
nod /dev/console 644 0 0 c 5 1
dir /sys 755 0 0
5、修改u-boot的启动参数
setenv bootcmd nand read 30008000 100000 500000;bootm 30008000//启动500000为内核镜像文件大小
接下来,当系统启动的时候,会自动加载linux内核镜像中的.init.ramfs中的内容到rootfs中,以此作为根目录


ramdisk与initramfs区别

本小节参考自:http://blog.csdn.net/laohuang1122/article/details/8241398
配置ramdisk需要设置
a. General Setup —> 选择init RAM filesystem and RAM disk
b. Device Drivers —> Block devices —> RAM block device support
c. (4096)Default RAM disk size kbytes等相关选项保持默认
d. File systems选择Second extended fs support

配置initramfs
initramfs不像ramdisk需要在内存中模拟一个磁盘,他所需的配置很少。
a. General Setup —> 选择init RAM filesystem and RAM disk
b. 指定Initramfs source file(s)

因为initramfs根文件系统启动时执行的第一个程序是init,而不是linuxrc,所以在此,我们制作的根文件系统需要添加一个init文件,相应的linuxrc文件就不再需要了。按照如下方式修改根文件系统
ln -s bin/busybox init
这样就为busybox创建了一个软链接init,这个文件就是我们要创建的init文件。

另外就是我们制作ramdisk根文件系统镜像的时候使用的是genext2fs工具,在此我们制作initramfs根文件系统镜像时,并不需要额外的步骤,而是在你编译Linux内核的时候就自动生成了。自动生成的initramfs根文件系统镜像在Linux源码树的usr目录下。名字叫initramfs_data.cpio.gz,它是gz格式的压缩文件。

initramfs制作方式将根文件系统直接编译到内核镜像中了,这样合二为一的镜像就不用单独烧写根文件系统镜像了,并且,在启动内核时的参数也就不用像ramdisk那样需要添加initrd=…来指定initramfs的位置了。
如果你不想将initramfs合并到内核中,直接用配置ramdisk的内核来启动即可,不过这时必须用initrd=…来指定initramfs的位置,并且第二个参数initranfs根文件系统镜像的大小必须指定为实际大小,否则提示镜像校验错误,无法启动内核。将uImage和initramfs_data.cpio.gz下载到内存,设置启动参数initrd=bufptr,size,就可以像ramdisk一样启动initramfs的根目录了。


initramfs原理

本小节参考自:http://blog.csdn.net/laohuang1122/article/details/8243271
initramfs与initrd类似,也是初始化好了且存在于ram中的,可以压缩也可以不压缩。但是目前initramfs只支持cpio包格式,它会被populate_rootfs()->unpack_to_rootfs(&_initramfs start, &__initramfs_end - &__initramfs_start, 0)函数(解压缩、)解析、安装。
initramfs与initrd的区别
1)Linux内核只认cpio格式的initramfs文件包(因为unpack_to_rootfs只能解析cpio格式文件),非cpio格式的initramfs文件包将被系统抛弃,而initrd可以是cpio包也可以是传统的印象(image)文件,实际使用中initrd都是传统印象文件。

2)initramfs在编译内核的同时被编译并与内核连接成一个文件,它被链接到地址__initramfs_star处,与内核同时被bootloader加载到ram中,而initrd是另外单独编译生成的,是一个独立的文件,它由bootloader单独加载到ram中内核空间外的地址,比如加载的地址为addr(是物理地址而非虚拟地址),大小为8MB,那么只要在命令行中加入“initrd=addr,8M”命令系统就可以找到initrd(当然通过适当修改Linux的目录架构、makefile文件和相关代码,以上两种情况都是可以相通的)。

3)initramfs被解析处理后其原始的cpio包(压缩或非压缩)所占的空间(&__initramfs_start&__initramfs_end)是作为系统的一部分一直保留在系统中,不会被释放掉,而对于initrd的印象(image)文件,如果没有在命令行中设置“keepinitrd”命令,即keep_initrd全局变量等于0,那么initrd印象文件被处理后其原始文件(压缩或非压缩)所占的空间(initrd_startinitrd_end)将被释放掉。

4)initramfs可以独立于ram disk单独存在,而要支持initrd必须首先支持ramdisk,即要配置CONFIG_BLK_DEV_INITRD选项首先必须配置CONFIG_BLK_DEV_RAM,因为initrd image实际就是初始化好了的ram disk印象文件,最后都要解析、写入到ram disk设备/dev/ram或/dev/ram0中。
initramfs相关全局变量

__initramfs_start
char数据类型,&__initramfs_start就是initramfs的cpio包起始虚拟地址。
__initramfs_end
char数据类型,&__initramfs_end就是initramfs的cpio包结束虚拟地址。
initramfs被编译链接的位置
initramfs被链接到&__initramfs_start虚拟地址处,属于.init.ramfs区,&__initramfs_start和&__initramfs_end在链接文件arch/arm/kernel/vmlinux.lds.S中定义如下:
__initramfs_start = .;
usr/built-in.o(.init.ramfs);所以initramfs文件实际就是usr目录下的built-in.o文件
__initramfs_end = .;
.init.ramfs在Linux2.6.10/usr/initramfs_data.S中定义,编译内核时会先编译Linux2.6.10\usr\gen_init_cpio.c生成应用程序gen_init_cpio;然后用gen_init_cpio生成Linux2.6.10\usr\ initramfs_data.cpio(.gz),它就是保存在&__initramfs_start与&__initramfs_end之间的.init.ramfs;可以通过修改Linux2.6.10\usr\Makefile文件将来使得编译链接时是否压缩initramfs。
initramfs文件的生成过程
1)cpio包格式二进制initramfs文件是由gen_init_cpio命令生成的,gen_init_cpio应用程序是由Linux2.6.10/gen_init_cpio.c文件编译而来,gen_init_cpio命令格式和用法说明如下。
gen_init_cpio命令格式:
# ./gen_init_cpio
Usage:
./gen_init_cpio <cpio_list>
<cpio_list>文件格式:
# a comment ;注释行;
file ;描述initramfs中的一个文件
dir ;描述initramfs中的一个目录
nod <dev_type> ;描述initramfs中的一个节点
<cpio_list>文件每一行各字段说明:
:该文件/目录/节点在initramfs中的名字,包含绝对路径
:该文件/目录/节点在当前开发主机上的位置
:该文件/目录/节点的模式字
:该文件/目录/节点的用户id,0表示root用户
:该文件/目录/节点的组id,0表示root组
<dev_type> :该设备节点对应设备的类型,b表示块设备,c表示字符设备
:设备节点对应设备的主设备号
:设备节点对应设备的次设备号
<cpio_list>文件示例:
# Last modified: 1206050528

dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
dir //lost+found 700 0 0
dir //bin 755 0 0
file //bin/addgroup /home/whh/tmp/bin/addgroup 777 0 0
file //bin/adduser /home/whh/tmp/bin/adduser 777 0 0

2)<cpio_list>文件生成方式
方法一:根据上述<cpio_list>文件格式说明自行编写。
方法二:写一个脚本文件一次性为指定目录下的每个文件/目录/节点生成一行描述符,并将它们全部写入一个指定的<cpio_list>文件中。在Linux2.6.10原始目录下的scripts\gen_initramfs_list.sh就是这样的脚本文件。它的使用方法如下:
# . ./gen_initramfs_list.sh <cpio_list文件>或<目录> > <my_cpio_list>
将把生成的所有文件、目录、节点的描述行写入文件my_cpio_list中。如果命令行中没有指定<cpio_list文件>和<目录>,那么gen_initramfs_list.sh会自行生成一个最简单的initramfs_list文件,如下所示:
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
3)配置并编译initramf
将要作为initramfs的目录放在某个目录下,如“/home/my_root/”目录。或者将已经写好的<cpio_list>文件放在某个目录下,如“/home/my_list”。
将内核配置文件myconfig中的
CONFIG_INITRAMFS_SOURCE=""
改成
CONFIG_INITRAMFS_SOURCE="/home/my_root"
或者
CONFIG_INITRAMFS_SOURCE="/home/my_list"
执行
# make myconfig
# make
或者将上面两步改成如下形式并执行:
# make menuconfig
在逐级弹出的
“Block devices”->“Source directory or cpio_list”
子菜单下输入:
/home/my_root
或者
/home/my_list
然后执行
# make
4)Linux2.6.10中cpio包格式二进制initramfs文件实际产生流程
Linux2.6.10中cpio包格式二进制initramfs文件实际产生过程是:第一步,gen_initramfs_list.s为指定目录“/home/my_root”或文件“/home/my_list”在Linux2.6.10/usr目录下生成真正的<cpio_list>文件initramfs_list;第二步,gen_init_cpio按照initramfs_list文件描述将对应的目录/home/my_root生成二进制cpio包initramfs_data.cpio;第三步,gzip将initramfs_data.cpio压缩成initramfs_data.cpio.gz;第四步,ld -m elf_i386 --format binary --oformat elf32-i386 -r -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o生成initramfs_data.o;第五步,ld -m elf_i386 -r -o built-in.o initramfs_data.o最后生成built-in.o。

5)从arm中编译出的内核印象文件Image、编译连接文件vmlinux.lds.S、cpio格式initramfs二进制压缩文件initramfs_data.cpio.gz、编译连接符号文件System.map对照看,事实上链接到&__initramfs_start位置的就是initramfs_data.cpio.gz文件。


参考文章

1\ 制作initramfs根文件系统
http://blog.csdn.net/laohuang1122/article/details/8241398
http://blog.csdn.net/pengrui18/article/details/14389233

2\ initramfs的原理
http://blog.csdn.net/laohuang1122/article/details/8243271

3\ 其他
http://womendu.iteye.com/blog/1069948

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckywang1103

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值