加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【原】initramfs挂载过程(HiS)

(2014-02-26 10:19:06)
标签:

linux

initramfs

rootfs

嵌入式

it

分类: Linux-文件系统

initramfs挂载过程(HiS)

使用内存作为第一个rootfs的相关技术目前查到有三个:一个是版本较老的initrd(号称:传统格式),处理过程麻烦;另外一个是相对较新cpio-initrd,处理过程相对简单清晰,这两个本文不做介绍。

本文重点记录了针对HiS3716C的开发板的initramfs挂载过程(这个也属于cpio格式,存在于内核之中),其中一些函数功能介绍文字来源于网络博客。

一 编译配置

编译内核时,编译内核脚本里指明了ramdisk的目录,即

make -j $JOBS uImage CONFIG_INITRAMFS_SOURCE="../out/target/product/godbox/root"

执行menuconfig后,相关的ramdisk的选项也已经选上。http://s5/mw690/001pjfmXzy6GST448Ly64&690

可见,ramdisk编译进了内核。

二 挂载过程分析

2.1 vfs_cache_init

init/main.c start_kernel

-->fs/dcache.c vfs_cache_init

vfs_cache_init中,重要操作mnt_init()会创建一个rootfs,这是个虚拟的rootfs,即内存文件系统

2.2 mnt_init

mnt_init中,重要操作有两个:

2.2.1 init_rootfs() 创建虚拟根文件系统(注册rootfs,根文件系统)

2.2.2 init_mount_tree 挂载根文件系统

2.3 init_mount_tree

init_mount_tree中,有两个重要操作,

2.3.1 mnt do_kern_mount("rootfs", 0, "rootfs", NULL); 创建虚拟文件系统

2.3.2 set_fs_root(current->fs, &root); 将当前的文件系统配置为根文件系统。

可能有人会问,为什么不直接把真实的文件系统配置为根文件系统?

因为,内核中没有根文件系统的设备驱动,如USB等存放根文件系统的设备驱动,而且即便你将根文件系统的设备驱动编译到内核中,此时它们还尚未加载,其实所有的Driver是由在后面的Kernel_Init线程进行加载。所以需要CPIO InitrdInitrdRAMDisk Initrd。另外,我们的Root设备都是以设备文件的方式指定的,如果没有根文件系统,设备文件怎么可能存在呢?

2.4 kernel_init

接下来,kernel_start最后会去调用rest_init()并会去创建系统中的第一个进程kernel_init,并由其调用所有模块的初始化函数。有三个重要操作

2.4.1 do_basic_setup

函数do_basic_setup()调用所有模块的初始化函数,包括initramfs的初始化函数populate_rootfs。这部分代码在init/initramfs.c,函数populate_rootfs通过如下方式导出: rootfs_initcall(populate_rootfs);

populate_rootfs中,有如下重要操作,HiS开发板只用了“操作(1)”:

(1) char *err unpack_to_rootfs(__initramfs_start, __initramfs_size);   

解压包到rootfs,其实,initramfs也是压缩过后的cpio文件。

(2) if (initrd_start) {

   判断是否加载了Initrd,无论对于那种格式的Initrd,即无论是CPIO-Initrd还是Image-InitrdU-Boot都会将其拷贝到initrd_start。当然了,如果是initramfs的情况下,该值肯定为空了。

(3) #ifdef CONFIG_BLK_DEV_RAM

   判断加载的是不是cpio-initrd接下来:

   如果不是cpio-initrd,则就是传统格式image-initrd,将其内容保存到文件/initrd.image中。在根文件          

       系统中创建文件/initrd.image,然后进行写操作等

     如果是cpio-initrd,则直接解压。

2.4.2 if (!ramdisk_execute_command) ramdisk_execute_command "/init";

ramdisk_execute_command值通过“rdinit=”指定,如果未指定,则采用默认的值/init

2.4.3 if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {

ramdisk_execute_command NULL;

prepare_namespace();}

检查根文件系统中是否存在文件ramdisk_execute_command,如果存在的话则往下执行init_post(),否则执行prepare_namespace()挂载根文件系统。HiS是直接执行init_post,在init_post中,重要操作是执行init脚本。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有