linux启动--文件系统初始化

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux启动--vfs相关初始化

内核在启动时对文件系统的初始化,主要完成的工作是为vfs中各种数据结构申请缓存,初始化散列表,并加载rootfs作为当前进程的根文件系统。

1、start_kernel( )中与文件系统相关的初始化

start_kernel( )

{

...

vfs_caches_init_early(); //fs/dcache.c完成dentry,inode散列表的初始化。

....

vfs_caches_init(); //fs/dcache.c

....

proc_root_init();

nsfs_init();

...

}

本节对上面函数逐一进行分析。

2、vfs_caches_init_early( )

// fs/dcache.c

void __init vfs_caches_init_early(void)

{

dcache_init_early();

inode_init_early();

}

dcache_init_early()在fs/dcache.c中主要完成目录结构dentry的散列表初始化。

inode_init_early()在fs/inode.c中主要完成inode结构散列表的初始化。

3 、vfs_caches_init( )

此函数在fs/dcache.c是文件系统初始化的主要函数。

void __init vfs_caches_init(void)

{

names_cachep = kmem_cache_create("names_cache", P ATH_MAX, 0,

SLAB_HWCACHE_ALIGN|SLAB_P ANIC, NULL);

dcache_init(); //fs/dcache.c

inode_init(); //fs/inode.c

files_init(); //fs/file_table.c

files_maxfiles_init(); //fs/file_table.c

mnt_init(); // fs/namespace.c

bdev_cache_init();

chrdev_init();

}

3.1、vfs_caches_init( ) →dcache_init()

dcache_init()在fs/dcache.c中,主要完成dentry结构缓存的申请和初始化。

3.2、vfs_caches_init( ) → inode_init()

inode_init()在fs/inode.c中主要完成inode结构缓存的申请和初始化。

3.3、vfs_caches_init( ) → files_init()

files_init()在fs/file_table.c中主要也是完成file结构缓存的申请和初始化。

3.4 vfs_caches_init( ) → files_maxfiles_init()

files_maxfiles_init()也在fs/file_table.c中,设置打开最大文件数。

以上几个函数都比较简短,功能也比较简单,基本上就是完成vfs中用到的inode,dentry,file等结构体内存缓存的申请和散列表的初始化。

3.3、vfs_caches_init( ) → mnt_init( ): // fs/namespace.c

mnt_init()是与vfs相关初始化的主要函数,位于fs/namespace.c中:

void __init mnt_init(void)

{

...

kernfs_init(); //fs/kernfs/inode.c

...

err = sysfs_init(); //fs/sysfs/mount.c注册并挂载sysfs。

...

init_rootfs(); //init/do_mount.c

init_mount_tree(); //fs/namespace.c

}

此函数完成,mount结构及散列表的初始化,内核文件系统及sys文件系统初始化。这里我们先关注最后两个函数。

init_rootfs()完成ramfs文件在内核的注册,由于内核启动前期无法访问外部块设备内的文件系统,所以启动时期必须先加载内存文件系统ramfs或叫rootfs。加载它的目的是用于系统初始化和加载块设备驱动程序,以便在启动后期加载块设备上的文件系统。

重点来看init_mount_tree(void),位于fs/namespace.c:

static void __init init_mount_tree(void)

{

struct path root;

...

type = get_fs_type("rootfs");

...

mnt = vfs_kern_mount(type, 0, "rootfs", NULL); /*在本文件内*/

root.mnt = mnt;

root.dentry = mnt->mnt_root;

mnt->mnt_flags |= MNT_LOCKED;

set_fs_pwd(current->fs, &root); //设置当前进程的当前目录。

set_fs_root(current->fs, &root); //设置当前进程的根目录,即加载当前目录为根目录。

}

浏览源代码可看出,此函数的任务就是加载rootfs文件系统,并将当前进程的当前目录和根目录设为rootfs的挂载点。

rootfs也就是ramfs,由于它是存在于内存中的文件系统,所以内核在加载时就得将文件系统一并加载。如果配置时启用了initramfs,则需在构建前将该文件系统的内容设置好,在配置时一并将路径加入配置选项中,内核在构建时就会将文件系统的内容压缩链接入内核中的一个段中,在内核启动时再解压释放到内存中,从而就可以访问文件系统内了。

解压函数在init/initramfs.c中:

static int __init populate_rootfs(void)

{

char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);

....

}

rootfs_initcall(populate_rootfs);

由最后一个宏定义可知,此函数会在启动时期调用。关于根文件系统的加载和制作在下一篇文章中再做介绍。

4、vfs_caches_init( ) →bdev_cache_init()

此函数位于fs/block_dev.c:

void __init bdev_cache_init(void)

{

int err;

static struct vfsmount *bd_mnt;

bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),

0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|

SLAB_MEM_SPREAD|SLAB_P ANIC),

init_once);

相关文档
最新文档