分类: Android平台
2015-06-01 14:47:51
initramfs概述
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_start处,与内核同时被 bootloader加载到ram中,而initrd是另外单独编译生成的,是一个独立的文件,它由bootloader单独加载到ram中内核空间外的地址,比如加载的地址为addr(是物理地址而非虚拟地址),大小为8MB,那么只要在命令行加入"initrd=addr,8M"命令,系统就可以找到 initrd(当然通过适当修改Linux的目录结构,makefile文件和相关代码,以上两种情况都是可以相通的)。
(3) initramfs被解析处理后原始的cpio包(压缩或非压缩)所占的空间(&__initramfs_start - &__initramfs_end)是作为系统的一部分直接保留在系统中,不会被释放掉,而对于initrd镜像文件,如果没有在命令行中设置"keepinitd"命令,那么initrd镜像文件被处理后其原始文件所占的空间(initrd_end - initrd_start)将被释放掉。
(4) initramfs可以独立ram disk单独存在,而要支持initrd必须要先支持ram disk,即要配置CONFIG_BLK_DEV_INITRD选项 -- 支持initrd,必须先要配置CONFIG_BLK_DEV_RAM -- 支持ram disk ,因为initrd image实际就是初始化好了的ramdisk镜像文件,最后都要解析、写入到ram disk设备/dev/ram或/dev/ram0中。
注: 使用initramfs,命令行参数将不需要"initrd="和"root="命令? YES
initramfs利弊:
------------------------------------------------------
由于initramfs使用cpio包格式,所以很容易将一个单一的文件、目录、node编译链接到系统中去,这样很简单的系统中使用起来很方便,不需要另外挂接文件系统。
但是因为cpio包实际是文件、目录、节点的描述语言包,为了描述一个文件、目录、节点,要增加很多额外的描述文字开销,特别是对于目录和节点,本身很小额外添加的描述文字却很多,这样使得cpio包比相应的image文件大很多。
使用initramfs的内核配置(使用initramfs做根文件系统):
------------------------------------------------------
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(/rootfs_dir) Initramfs source file(s) //输入根文件系统的所在目录
使用initramfs的内核启动参数
不需要"initrd="和"root="参数,但是必须在initramfs中创建/init文件或者修改内核启动最后代码(init文件是软连接,指向什么? init -> bin/busybox,否则内核启动将会失败)
链接入内核的initramfs文件在linux-2.6.24/usr/initramfs_data.cpio.gz
使用initrd的内核配置(使用网口将根文件系统下载到RAM -- tftp addr ramdisk.gz):
------------------------------------------------------
1. 配置initrd
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
() Initramfs source file(s) //清空根文件系统的目录配置
2. 配置ramdisk
Device Drivers --->
Block devices --->
<*> RAM disk support
(16) Default number of RAM disks // 内核在/dev/目录下生成16个ram设备节点
(4096) Default RAM disk size (kbytes)
(1024) Default RAM disk block size (bytes)
使用 initrd的内 核启动参数:
initrd=addr,0x400000 root=/dev/ram rw
注:
(1) addr是根文件系统的下载地址;
(2) 0x400000是根文件系统的大小,该大小需要和内核配置的ramdisk size 4096 kbytes相一致;
(3) /dev/ram是ramdisk的设备节点,rw表示根文件系统可读、可写;
根文件系统存放在FLASH分区:
------------------------------------------------------
1. 内核启动参数不需要"initrd="(也可以写成"noinitrd");
root=/dev/mtdblock2 (/dev/mtdblock2 -- 根文件系统所烧写的FLASH分区)
2. 内核配置不需要ram disk;也不需要配置initramfs或者initrd
[ ] Initial RAM filesystem and RAM disk (initramfs/initrd) support
注: boot的FLASH分区要和kernel的FLASH分区匹配(而非一致),需要进一步解释。
TCP reno registered 停在这里
---------------------------------------------
rootfs太大,检测发现rootfs下有垃圾(里面有包含了一份rootfs)
下面这个大小启动成功了
---------------------------------------------
root@zengxiaolong:/home/zengxiaolong/soft/s3c2410/rootfs# du -h
4.0K ./dev
4.0K ./tmp
8.0K ./etc/init.d
40K ./etc
4.0K ./usr
4.0K ./var
4.0K ./sbin
2.1M ./bin
4.0K ./sys
116K ./lib/modules
2.8M ./lib
4.0K ./proc
4.9M .
initrd and initramfs
http://blog.sina.com.cn/s/blog_622013d90100fr04.html
---------------------------------------------
#
# General setup
#
...
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="
...
#
# UBI - Unsorted block images
#
...
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
Installation initramfs
No special installation like with initrd is necessary. The initramfs is already in the kernel. If you start the kernel, the initramfs is already there. Therefore, there is no root=/dev/ram0 rw initrd=0x87000000,8M bootargs option necessary. Remove this if you still have it!
http://blog.chinaunix.net/uid-488742-id-2113871.html
下面两篇文章是ARM9论坛上的讲解ramdisk文件系统的很不错的文章
今天做了个试验,让Linux2.6.29.4从ramdisk根文件系统启动成功,总结一下。
其中涉及的内容较多,很多东西不再详述,如需深入研究请查阅相关资料(百度或谷歌一下一大堆)。好像友善之臂把内核源码目录里的uImage目标给注释了,以前在论坛里看到过有人说,直接make uImage好像提示没有uImage的目标。所以我就先制作zImage,然后再用u-boot的mkimage工具转化为uImage。其实uImage就是在zImage的开头部分增加了一个64字节的内核映像说明。说明一下:zImage是ARM Linux常用的一种压缩映像文件,uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImage的0x40位置开始执行,zImage和uImage没有任何区别。另外,Linux2.4内核不支持uImage,Linux2.6内核加入了很多对嵌入式系统的支持,但是uImage的生成也需要设置。
锻炼一下自己分析解决问题的能力吧。呵呵。
initramfs与initrd类似,也是初始化好了且存在于ram中的,可以压缩也可以不压缩。但是目前initramfs只支持cpio包格式,它会被populate_rootfs()->unpack_to_rootfs(&__initramfs_ start, &__initramfs_end - &__initramfs_start, 0)函数(解压缩、)解析、安装。
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_start
char数据类型,&__initramfs_start就是initramfs的cpio包起始虚拟地址。
__initramfs_end
char数据类型,&__initramfs_end就是initramfs的cpio包结束虚拟地址。
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。
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
方法一:根据上述
文件格式说明自行编写。 方法二:写一个脚本文件一次性为指定目录下的每个文件/目录/节点生成一行描述符,并将它们全部写入一个指定的
文件中。在Linux2.6.10原始目录下的scripts\gen_initramfs_list.sh就是这样的脚本文件。它的使用方法如下: # . ./gen_initramfs_list.sh
或<目录> > 将把生成的所有文件、目录、节点的描述行写入文件my_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
将要作为initramfs的目录放在某个目录下,如“/home/my_root/”目录。或者将已经写好的
文件放在某个目录下,如“/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
Linux2.6.10中cpio包格式二进制initramfs文件实际产生过程是:第一步,gen_initramfs_list.s为指定目录“/home/my_root”或文件“/home/my_list”在Linux2.6.10/usr目录下生成真正的
文件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。