`
womendu
  • 浏览: 1528177 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

rootfs初始化调用层次关系

阅读更多

本文相对简单得罗列出函数调用层次

start_kernel()
--> vfs_caches_init_early()
--> dcache_init_early()
// 创建目录项hash表,并将hash表每个入口指针均置成NULL
--> inode_init_early()
// 创建文件节点hash表,并将hash表每个入口指针均置成NULL
--> vfs_caches_init(num_physpages)
--> names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL)
// 创建slub高速缓存组names_cache,被格式化成PATH_MAX = 4096,该高缓用指针names_cachep指向的
// struct kmem_cache 结构体描述
--> dcache_init()
--> dentry_cache = KMEM_CACHE(dentry,SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD)
// 创建slub高速缓存组dentry,被格式化成struct dentry,该高缓用指针dentry_cache指向的
// struct kmem_cache 结构体描述
--> register_shrinker(&dcache_shrinker)
// 注册针对dentry高缓的页面回收函数shrink_dcache_memory,由页面回收算法(PFRA)来定期执行
--> inode_init()
--> inode_cachep = kmem_cache_create("inode_cache",
sizeof(struct inode),
0,
(SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD),
init_once);
// 创建slub高速缓存组inode_cache,被格式化成struct inode,该高缓用指针inode_cachep指向的
// struct kmem_cache 结构体描述
--> register_shrinker(&icache_shrinker)
// 注册针对inode_cache高缓的页面回收函数shrink_icache_memory,由页面回收算法(PFRA)来定期执行
--> files_init(mempages)
--> filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
// 创建slub高速缓存组filp,被格式化成struct file,该高缓用指针filp_cachep指向的
// struct kmem_cache 结构体描述
--> files_stat.max_files = ?
// 设置全局结构体对象的max_files域
--> ..
--> mnt_init() // 非常重要函数
--> mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL)
// 创建名为mnt_cache的slab高速缓存,格式化成struct vfsmount,由指针mnt_cache指向的结构体描述
--> 必须分配到一页物理内存作为mount_hashtable数组的空间,同时将该hash表每个入口项的指针next、prev
初始化成NULL
--> sysfs_init() // sys文件系统初始化,注册,挂载
--> sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
sizeof(struct sysfs_dirent),
0, 0, NULL);
--> sysfs_inode_init()
--> register_filesystem(&sysfs_fs_type)
// 注册,将sysfs的描述结构体sysfs_fs_type挂接到全局链表file_system中
--> kern_mount(&sysfs_fs_type)
// 挂载sysfs,该函数后面再rootfs时也会用,所以在后面分析它
--> kobject_create_and_add("fs", NULL)
// 在sysfs目录下创建fs目录,主要是创建名为fs的kobject及相关初始化
--> init_rootfs() // rootfs注册
--> bdi_init(&ramfs_backing_dev_info)
--> register_filesystem(&rootfs_fs_type)
// 注册roofs,将rootfs的描述结构体rootfs_fs_type挂接到全局链表file_system中
--> init_mount_tree() // mnt_init调用的重要函数
// 挂载rootfs文件系统
--> struct vfsmount *mnt // 描述文件系统挂载的结构体对象指针
struct mnt_namespace *ns // 名字空间
struct path root // root.mnt 和root.dentry
--> mnt = do_kern_mount("rootfs", 0, "rootfs", NULL)
// /* 重要函数 挂载前面已经注册进内核的rootfs文件系统*/
--> struct file_system_type *type = get_fs_type(fstype) // 找到file_system链表中对应名字
// 的file_system_type结构体地址
struct vfsmount *mnt; // 描述文件系统挂载的结构体对象指针
--> mnt = vfs_kern_mount(type, flags, name, data)
// flags = 0 , data = NULL , name = "rootfs"
--> struct vfsmount *mnt
--> mnt = alloc_vfsmnt(name)
// 在slub高速缓存组mnt_cache中分配一个vfsmount对象,并对其进行初始化,name = rootfs
// 引用计数 = 1
--> data = NULL ,没有数据需要处理
--> error = type->get_sb(type, flags, name, data, mnt)// type->get_sb = rootfs_get_sb
<==> error = rootfs_get_sb(type, flags, name, data, mnt)
--> get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, mnt)
--> struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL)
--> struct super_block *s = NULL
--> s = alloc_super(type)
// 直接利用kmalloc来分配内存,并做相应初始化
--> err = set(s, data) // set = set_anon_super
<==> set_anon_super(s, data)
--> s->s_type = type // = &rootfs_fs_type
--> strlcpy(s->s_id, type->name, sizeof(s->s_id)) // name copy "rootfs"
--> list_add_tail(&s->s_list, &super_blocks)
// 将该超级块添加到全局超级块链表super_blocks中去
--> list_add(&s->s_instances, &type->fs_supers)
// 将该超级块添加到该文件系统描述结构体中的本文件系统超级块链表中
--> get_filesystem(type) // 这里该函数什么都没做
--> s->s_flags = flags // = MS_NOUSER
--> error = fill_super(s, data, flags & MS_SILENT ? 1 : 0) // 超级块填充函数
<==> error = ramfs_fill_super(s, data, 1)
--> struct inode * inode // 文件节点
struct dentry * root // 目录项root
--> sb->s_maxbytes = MAX_LFS_FILESIZE;/* 文件的最大值 */
sb->s_blocksize = PAGE_CACHE_SIZE;/* 以字节为单位的块的大小 */
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;/* 以位为单位的块的大小 */
sb->s_magic = RAMFS_MAGIC; /* 文件系统的魔数 */
sb->s_op = &ramfs_ops; /* 超级块的方法 ,在处理inode的时候会有用 */
sb->s_time_gran = 1;
--> inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);
/* 建立根目录索引节点 */
--> struct inode * inode = new_inode(sb)
/* 在索引节点高速缓存inode_cachep中创建一个inode,
并初始化话相应的域*/
--> inode = alloc_inode(sb)
--> inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL)
--> inode_init_always(sb, inode)
--> inode->i_sb = sb
// 其余初始化项省略
--> inode->i_mode = mode;/* 文件的类型 */
inode->i_blocks = 0;//文件的块数
再通过一个switch语句判断是什么文件类型,初始化相应的操作方法
其余省略
--> root = d_alloc_root(inode);/* 建立根目录目录对象,并关联上inode */
--> static const struct qstr name = { .name = "/", .len = 1 }
// 看到根目录的符号了吧!呵呵
--> res = d_alloc(NULL, &name)
// 从slub高缓dentry_cache中分配一个目录对象的内存,并做相应初始化
--> res->d_sb = root_inode->i_sb; //指向该文件系统的超级块
res->d_parent = res; //根目录的父亲当然是它自己了
--> d_instantiate(res, root_inode)//将dentry 和 inode关联上
--> sb->s_root = root; /* 超级块的s_root指向刚建立的根目录对象 */
--> s->s_flags |= MS_ACTIVE
--> simple_set_mnt(mnt, s)
/* 超级块和文件系统挂载结构体简单关联 */
--> mnt->mnt_sb = sb
mnt->mnt_root = dget(sb->s_root)
--> security_sb_kern_mount(mnt->mnt_sb, flags, secdata)
--> mnt->mnt_mountpoint = mnt->mnt_root
//指明挂载点,其实就是刚才建立的”/”目录
--> mnt->mnt_parent = mnt
//父对象是自己
--> return mnt
--> put_filesystem(type) // wake_up_process()
--> return mnt
--> ns = kmalloc(sizeof(*ns), GFP_KERNEL)
// 分配名字空间结构体的内存
--> atomic_set(&ns->count, 1) // 设置ns的引用计数
--> INIT_LIST_HEAD(&ns->list) // 连接体初始化
--> init_waitqueue_head(&ns->poll) // 初始化等待队列头
--> list_add(&mnt->mnt_list, &ns->list)
// 将该vfsmount结构体挂接到namespace结构体的链表中
--> ns->root = mnt
// 该命名空间结构体的root域指向刚刚建立的vfsmount结构体
--> mnt->mnt_ns = ns
// 该vfsmount结构体的命名空间域指向ns
--> init_task.nsproxy->mnt_ns = ns
--> root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);
// 最后这几行通过中间变量root,将 do_kern_mount() 函数中建立的 mnt 和 dentry
// 信息记录在了当前进程的fs结构中
--> bdev_cache_init()
--> chrdev_init()

***vfs_caches_init() end.
至此,sysfs和rootfs文件系统初始化挂载完成。

分享到:
评论

相关推荐

    rootfs根文件系统的构建

    根文件系统可以以镜像文件形式存在,需要使用专门工具软件将根文件所需文件制作成镜像,镜像格式与制作工具有关,烧录此镜像时类似于对相应分区初始化。另一种形式是文件夹形式,实质是包含特定内容的文件夹,可以在...

    系统boot过程详解

    - **mnt_init**:初始化函数,负责调用`init_rootfs`和`init_mount_tree`来创建和初始化rootfs。 - **初始化流程**:通过调用`rootfs_initcall(populate_rootfs)`函数来实现,该函数在`do_initcalls`阶段被调用。 ...

    start_kernel()代码分析

    1. **调用关系**: - `start_kernel()` -&gt; `trap_init()`:这是中断向量表初始化的主要入口。 - `trap_init()`和`init_IRQ()`:分别负责不同的初始化工作。 2. **`trap_init()`详解**: - **实现位置**:`linux/...

    uboot 启动远程 Kernel(TFTP)以及挂载远程 ROOTFS(NFS)

    - 确保根文件系统中包含了必要的初始化脚本`/linuxrc`。 8. **完整的启动日志**: - 启动后,通过串口终端或日志文件查看启动过程。 - 确保每个步骤都按预期执行。 通过以上步骤,可以成功地利用U-Boot实现远程...

    解析linux根文件系统的挂载过程.pdf

    在`start_kernel()`函数中,`mnt_init()`被调用,这是文件系统初始化的起点。`init_rootfs()`函数注册了rootfs文件系统类型,通常是ramfs,这是一种内存中的临时文件系统,用于在真实文件系统挂载前提供基本的文件...

    linux 根文件系统

    当内核启动时,`start_kernel()`函数会调用`vfs_caches_init()`来初始化VFS。在这个过程中,`mnt_init()`函数被调用,它创建了一个虚拟的rootfs,这个rootfs是一个空的、基本的文件系统,允许内核在没有实际文件系统...

    mksquashfs

    **rootfs**(根文件系统)是操作系统启动时加载的第一个文件系统,它包含了操作系统的最基本组件,如系统调用表、初始化脚本、基本的系统命令等。在嵌入式系统中,rootfs通常是一个精简版的文件系统,包含启动系统所...

    解析linux根文件系统的挂载过程

    2. **mnt_init()**:在`start_kernel()`函数执行过程中,会调用`mnt_init()`函数进行挂载点和文件系统初始化。 - **init_rootfs()**:此函数用于注册rootfs文件系统类型,并初始化相应的数据结构。 ```c int _...

    update-reset:使用OverlayFS Linux内核功能实现的事务更新(和还原)系统。 包括用于构建和应用CoderBot更新包的脚本

    覆盖是通过初始化脚本安装的。 它安装上层文件系统,将rootfs和upper合并到overlayfs中,从而使其成为新的rootfs。 然后调用systemd。 如果引发了还原事件,它将清除高位fs。设置创建上部分区或使用part_overlay...

    需要了解linux根文件系统的挂载过程.docx

    这个脚本负责初始化系统环境、加载驱动程序和挂载真实的根文件系统。 3.切换根目录 执行 /linuxrc 脚本后,系统会切换根目录到真实的根文件系统。这个过程中,系统会卸载临时根文件系统 /dev/ram0,并装载真实的根...

    MiniTools-USB下载工具-20240321

    Bootloader是设备启动时运行的第一段代码,它负责加载操作系统到内存中并初始化必要的硬件。对于开发者和设备维护人员来说,更新或恢复bootloader可能是因为需要修复安全漏洞、优化启动速度或是兼容新的硬件。...

    基于NFC技术的智能门禁系统设计.pdf

    在uboot配置和编译中,通过配置uboot可以选择与我们cpu相关的文件,这些文件里面包含了我们初始化相关硬件的函数,这样在系统启动uboot时,可以对相关的硬件进行初始化,这样为后面的启动内核奠定基础。 在kernel...

    montavista linux的移植

    U-BOOT是嵌入式系统中的关键组件,负责初始化硬件、加载内核以及设置启动参数。在MPC8270开发板上移植U-BOOT,主要涉及以下几个步骤: 1. **Stage1和Stage2的编译与构建**:Stage1通常用汇编语言编写,用于初始化...

    一遍很好介绍VFS文件系统结构的文章

    rootfs文件系统是Linux内核初始化阶段不可缺少的一部分。它通常是在内存中构建的,提供了一个最小的文件系统环境,使得内核能够加载并启动更复杂的文件系统。 VFS中的文件操作机制涵盖了文件的读写、删除以及目录的...

    linux内存使用分析

    具体的加载处理流程涉及到多个步骤,其中包括`kernel_init`函数的调用以及`populate_rootfs`函数的执行,最终将文件系统数据解压并挂载。 #### 设备树的加载 设备树是一个包含硬件配置信息的特殊文件,它在系统...

    制作自己的Linux_OS.doc

    - **硬件初始化**:内核加载后,会检测并初始化系统中的各种硬件设备。 - **运行 init 程序**:内核最后运行`/sbin/init`程序,该程序根据`/etc/inittab`文件中的配置初始化系统服务。 - **用户登录**:init程序完成...

    lpunpack_and_lpmake-master.zip

    在实际使用中,开发者可能会根据项目需求对lpmake进行优化,例如添加自定义脚本以实现特定的初始化任务,或者集成自动化测试工具以提升镜像质量。此外,lpmake也可以与其他工具(如Linaro的image-builder)结合,...

    裁减操作系统脚本代码

    - 裁减初始化脚本:调整`/etc/rc.local`或`/etc/init.d`中的启动脚本,确保只运行必需的服务。 - 修剪文件系统:删除无用的文件、目录和库,优化占用空间。 - 创建新文件系统:使用`tar`命令将裁减后的目录打包为新...

    根文件制作

    - `etc`目录包含了系统启动和初始化所需的脚本和其他配置文件。 - 可以使用现有的`etc`目录压缩包,对其进行适当的修改后解压缩到`rootfs`目录下。 4. **使用BusyBox**: - BusyBox是一个轻量级的工具集,包含了...

Global site tag (gtag.js) - Google Analytics