do_initcalls 的打印信息
VFS: Mounted root (nfs filesystem) on device 0:10.
Freeing unused kernel memory: 1024K
- 函数分类
arch_call_rest_init
rest_init
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
kernel_init_freeable
smp_init
do_basic_setup
driver_init
do_initcalls
for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) do_initcall_level(level, command_line);
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) do_one_initcall(initcall_from_entry(fn));
/*
init/main.c
extern initcall_entry_t __initcall_start[]; // 来自于 include/asm-generic/vmlinux.lds.h
extern initcall_entry_t __initcall0_start[];
extern initcall_entry_t __initcall1_start[];
extern initcall_entry_t __initcall2_start[];
extern initcall_entry_t __initcall3_start[];
extern initcall_entry_t __initcall4_start[];
extern initcall_entry_t __initcall5_start[];
extern initcall_entry_t __initcall6_start[];
extern initcall_entry_t __initcall7_start[];
extern initcall_entry_t __initcall_end[];
static initcall_entry_t *initcall_levels[] __initdata = {
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
__initcall_end,
};
*/
prepare_namespace
mount_root
mount_nfs_root
do_mount_root
printk(KERN_INFO "VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
free_initmem
free_initmem_default
free_reserved_area(&__init_begin, &__init_end, poison, "unused kernel");
// free_initmem 回收 整个 初始化代码段 的内存空间
run_init_process
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
cpu_startup_entry(CPUHP_ONLINE);
do_idle
其他
设备安装流程区别
一般设备
安装点 已经存于于 文件系统中
/dev 目录找到 设备,得到设备号
知道设备的文件系统类型
mount -t ext2 /mnt /dev/sda1
do_mount
根设备
安装点 不在 文件系统中
/dev 目录 不存在, 设备号已经存在
不知道设备的文件系统类型,需要试凑
根设备安装流程
init->do_basic_setup->
filesystem_setup
init_devfs_fs
kern_mount
挂载 devfs 到 / 上
init->do_basic_setup->
mount_root
1. root_dev_setup 设置 root_device_name 为 /dev/sda1 中的 sda1
2. devfs_make_root 将 sda1 转换为 新的字符串,存放于 root_device_name 中
3. devfs_find_handle 在 devfs 中寻找 root_device_name,找到了就填充 ROOT_DEV 为 root_device_name 对应的设备号 // 一个设备对应一个设备号还是一个分区对应一个设备号
4. 之前 设备驱动层已经完成了初始化. bdget 根据 设备号 找到 block_device 架构体,devfs_get_ops找到设备的 block_device_operations 结构体,其中有open成员
5. blkdev_get 调用 block_device_operations 中的open 打开 设备
6. 并读 超级块 到 内存中的超级块队列,get_super 扫描 已经读入内存中的超级块队列,检索到该设备的超级块,知晓 设备上的文件类型,填充到 fs_type 中
6.1 get_super 调用 注册到 file_system_type 中的 文件系统中的 read_super,依次读取 该设备的超级块到内存,如果A文件系统的 reda_super 读取成功,代表该设备的文件系统为A文件系统
7. add_vfsmnt
// 以文件系统的根为本进程逻辑意义的根
8. set_fs_root 设置当前进程的 fs_struct 数据结构体中的 root 和 rootmnt 两个指针, 是他们分别指向 根节点的 dentry 数据结构 sd->s_root , 以及 安装跟设备时的 vfsmount 数据结构,vfsmnt
9. set_fs_pwd 将当前进程的 当前工作目录 , 即 pwd 和 pwdmnt 两个指针 也设置成指向这两个数据结构
此时根设备安装完毕
init->do_basic_setup->
mount_dev_fs 安装 devfs 到 /dev 上
do_mount