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、接下来,当系统启动的时候,会自动加载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_start~initrd_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
文件格式:
# a comment ;注释行;
file ;描述initramfs中的一个文件
dir ;描述initramfs中的一个目录
nod ;描述initramfs中的一个节点
文件每一行各字段说明:
:该文件/目录/节点在initramfs中的名字,包含绝对路径
:该文件/目录/节点在当前开发主机上的位置
:该文件/目录/节点的模式字
:该文件/目录/节点的用户id,0表示root用户
:该文件/目录/节点的组id,0表示root组
:该设备节点对应设备的类型,b表示块设备,c表示字符设备
:设备节点对应设备的主设备号
:设备节点对应设备的次设备号
文件示例:
# 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)文件生成方式
方法一:根据上述文件格式说明自行编写。
方法二:写一个脚本文件一次性为指定目录下的每个文件/目录/节点生成一行描述符,并将它们全部写入一个指定的文件中。在Linux2.6.10原始目录下的scripts\gen_initramfs_list.sh就是这样的脚本文件。它的使用方法如下:
# . ./gen_initramfs_list.sh
参考文章
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