Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531314
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2008-05-14 18:38:24

浅析linux2.6.24内核initrd传递给rootfs进行系统加载流程

1.解析有loader传递过来的initrd参数
start_kernel()->
setup_arch()->
parse_tags()->
使用下面这个函数进行解析:
static int __init parse_tag_initrd(const struct tag *tag)
{
    printk(KERN_WARNING "ATAG_INITRD is deprecated; "
        "please update your bootloader.\n");
    phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
    phys_initrd_size = tag->u.initrd.size;
    return 0;
}
__tagtable(ATAG_INITRD, parse_tag_initrd);

2.进一步初始化initrd_start变量
start_kernel()->
setup_arch()->
paging_init()->
bootmem_init()->
bootmem_init_node()->
在该函数中使用下面2个语句将物理地址转为虚拟地址
#ifdef CONFIG_BLK_DEV_INITRD
    ...
    initrd_start = __phys_to_virt(phys_initrd_start);
    initrd_end = initrd_start + phys_initrd_size;
    ...
#endif
3.建立rootfs文件系统,并mount到根目录
start_kernel()->
vfs_caches_init()->
mnt_init()->
init_rootfs()->位于fs/ramfs/inode.c中,调用register_filesystem(&rootfs_fs_type);注册rootfs
接下来
init_mount_tree()函数将调用mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);将rootfs挂在到/根目录下
然后使用如下两个函数,将后边建立线程的根目录指向rootfs,
set_fs_pwd(current->fs, ns->root, ns->root->mnt_root);
set_fs_root(current->fs, ns->root, ns->root->mnt_root);
4.将initrd(的ramdisk加载到rootfs
start_kernel()->
rest_init()->
kernel_init()->内核线程
do_basic_setup()->
do_initcalls()->调用所有arch/arm/kernel/vmlinux.lds.S中定义的INITCALLS模块,比如:使用module_init内建到zImage中的所有驱动模块

#define pure_initcall(fn)        __define_initcall("0",fn,0)
#define core_initcall(fn)        __define_initcall("1",fn,1)
#define core_initcall_sync(fn)        __define_initcall("1s",fn,1s)
#define postcore_initcall(fn)        __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn)    __define_initcall("2s",fn,2s)
#define arch_initcall(fn)        __define_initcall("3",fn,3)
#define arch_initcall_sync(fn)        __define_initcall("3s",fn,3s)
#define subsys_initcall(fn)        __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
#define fs_initcall(fn)            __define_initcall("5",fn,5)
#define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn)        __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn)        __define_initcall("6",fn,6)
#define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
#define late_initcall(fn)        __define_initcall("7",fn,7)
#define late_initcall_sync(fn)        __define_initcall("7s",fn,7s)

上面我们关心的是rootfs_initcall定义,
在init/initramfs.c中具体实现如下:
rootfs_initcall(populate_rootfs);
populate_rootfs()会调用下面这个函数将initrd的内容释放到rootfs文件系统下
unpack_to_rootfs((char *)initrd_start,initrd_end - initrd_start, 0);
这样initrd的ramdisk的内容全部释放到了rootfs文件系统中,所以ramdisk下的所有目录结构将全部被克隆到rootfs文件系统下,具体unpack_to_rootfs函数的实现流程,以后有时间再研究(gliethttp_20080514)

阅读(3430) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~