公众号【嵌入式er笔记】持续记录和分享C/C++、Linux、ARM、Android、IoT等技术相关知识,以及职场、生活经验和感悟。
分类: 嵌入式
2014-10-11 21:04:47
原文地址:关于initramfs 作者:hpuwangbo
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。