initRD的启动流程分析

1、根文件系统存放在flash中,设备启动过程中会耗时比较久时间。这是因为从flash中读取rootfs的数据操作比较耗时,同时读取存放在rootfs中的*.so,*.ko等文件也比较耗时。这都是由flash本身的读写属性决定的。对于一些需要快速启动的设备,flash的读写速率无法满足,因此可以考虑挂载到内存中的rootfs,即ramdisk。

2、使用ramdisk需要内核的支持,需要打开CONFIG_BLK_DEV_INITRD宏

3、initramfs初始化流程图如下图所示,主要分成两部分。
3.1、挂载rootfs(“/”),vfs_caches_init分支
3.2、制作rootfs,rest_init分支

4、建立rootfs

struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
	......
	root = mount_fs(type, flags, name, data);
	......
}
EXPORT_SYMBOL_GPL(vfs_kern_mount);

根据vfs_kern_mount函数传入的name="rootfs",最终会执行rootfs_mount完成根文件系统建立。

static struct file_system_type rootfs_fs_type = {
	.name		= "rootfs",
	.mount		= rootfs_mount,
	.kill_sb	= kill_litter_super,
};

5、制作根文件系统
5.1、如何从__initcall6_start到populate_rootfs
device_initcall(populate_rootfs);
populate_rootfs函数通过device_initcall宏,装载到特定的section中(.initcall6.init)

#define device_initcall(fn)		__define_initcall(fn, 6)
#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)
#define ___define_initcall(fn, id, __sec) \
	static initcall_t __initcall_##fn##id __used \
		__attribute__((__section__(#__sec ".init"))) = fn;

即device_initcall函数__initcall_populate_rootfs6存放在.initcall6.init的section中
通过//include/asm-generic/vmlinux.lds.h 链接脚本文件,发现

 当执行__initcall6_start函数时,就是执行存放在.initcall6.init这个section的数据,即__initcall_populate_rootfs6函数

5.2、制作rootfs

static int __init populate_rootfs(void)
{
	char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
	......
	if (initrd_start) {
		......
		printk(KERN_INFO "Unpacking initramfs...\n");
		err = unpack_to_rootfs((char *)initrd_start,
			initrd_end - initrd_start);
		if (err)
			printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
		free_initrd();

		/*
		 * Try loading default modules from initramfs.  This gives
		 * us a chance to load before device_initcalls.
		 */
		load_default_modules();
	}

	return 0;
}

5.2.1、先unpcak_to_rootfs的[__initramfs_start, __initramfs_start+__initramfs_size]数据
通过//include/asm-generic/vmlinux.lds.h 链接脚本文件,发现

其中定义了.init.ramfs和.init.ramfs.info两个section
通过//usr/initramfs_data.S文件发现,__initramfs_size大小由initramfs_data.o确定

其中INITRAMFS_IMAGE在//usr/Makefile文件中定义

initramfs加载后一般不会使用

5.2.2、后unpack_to_rootfs的[initrd_start, initrd_end]数据
其中initrd_end和initrd_start通过cmdline传入,并且数据在uboot阶段已经从flash的rootfs分区解压后搬迁到initrd_start地址。

5.2.2.1、flash镜像中rootfs的制作
rootfs通过cpio命令制作生成*.cpio的文件,根据压缩方式完成压缩(build\images.mk脚本中)

#lzo压缩方式,rootfs.bin是rootfs_initramfs.cpio经过lzo压缩后的文件
lzop -x rootfs.bin
#将cpio文件转换成目录格式,ls查看具体的目录内容
cpio -idmv < rootfs_initramfs.cpio 

 5.2.2.2、内存中rootfs的制作

static char * __init unpack_to_rootfs(char *buf, unsigned len)
{
	......
	while (!message && len) {
		loff_t saved_offset = this_header;
		if (*buf == '0' && !(this_header & 3)) {
			state = Start;
			written = write_buffer(buf, len);
			......
		}
		......
		this_header = 0;
		decompress = decompress_method(buf, len, &compress_name);
		if (decompress) {
			res = decompress(buf, len, NULL, flush_buffer, NULL,
				   &my_inptr, error);
			if (res)
				error("decompressor failed");
		} 
		......
	}
}

当前buf中的数据已经完成解压,直接通过write_buffer函数制作;不通过具体的压缩方式decompress后flush_buffer实现
write_buffer中通过以下函数解析buf数据,完成根文件系统的制作

static __initdata int (*actions[])(void) = {
	[Start]		    = do_start,
	[Collect]	    = do_collect,
	[GotHeader]	    = do_header,
	[SkipIt]	    = do_skip,
	[GotName]	    = do_name,
	[CopyFile]	    = do_copy,
	[GotSymlink]	= do_symlink,
	[Reset]		    = do_reset,
};

 

 6、运行跟文件系统中的应用程序

//kernel_init函数内,执行ramdisk_execute_command应用程序,其中ramdisk_execute_command从cmdline中传入
if (ramdisk_execute_command) {
	if (!run_init_process(ramdisk_execute_command))
		return 0;
	pr_err("Failed to execute %s\n", ramdisk_execute_command);
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值