内核的文件系统的注册
来源:互联网 发布:php y 编辑:程序博客网 时间:2024/06/01 09:28
在linux内核中的文件管理模块中,VFS机制居功至伟,VFS是virtual file system的缩写,表示为虚拟文件系统,它可以实现在Linux操作系统中可以同时有多个不同的文件系统在工作,并且不同文件系统之间的差异性对应用层是完全透明的。VFS本身并不是一种技术,而是多种技术手段和数据结构的集合,比如对进程抽象文件管理,如果将系统文件管理转换成对文件外存的块管理,如何加快对文件的操作,诸如这些所有,加在一起,就形成一种文件管理的机制,把这种机制中的一个中间部分,由内核来主要管理的、不依赖于具体的文件系统和驱动的、只提供接口不实现操作的部分,称为VFS机制。
这篇博文讨论内核中文件系统的注册。
一,文件系统往哪注册
在说明文件系统注册之前,先了解一些文件系统往哪注册,这本质上是内核如何管理所有已经被注册的文件系统。就是如果要添加一个文件系统至操作系统,此时内核将这个文件系统的信息将要保存在什么地方?
内核将文件系统保存在一个全局变量中,在源码文件filesystems.c文件中定义:
static struct file_system_type *file_systems;这是一个全局变量,保存所有的已经被系统注册的文件系统,所以可以想像到struct file_system_type肯定要维护链表之类的存储结构。
二,数据结构
每一个需要被注册的文件系统由下面的结构表示:
struct file_system_type {const char *name;int fs_flags;int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *);void (*kill_sb) (struct super_block *);struct module *owner;struct file_system_type * next;struct list_head fs_supers;struct lock_class_key s_lock_key;struct lock_class_key s_umount_key;struct lock_class_key i_lock_key;struct lock_class_key i_mutex_key;struct lock_class_key i_mutex_dir_key;struct lock_class_key i_alloc_sem_key;};对上面结构的字段说明如下:
- name:文件系统的名称。
- fs_flags:文件系统的属性和有些特性的设置。
- next:这个容易理解,维护链表上的多个文件系统。
- fs_supers:表示给定文件系统所对应的超级块链表的头结点,这里要理解超级块对象,可以先简单的理解成文件系统需要管理很多的外存储(就是硬盘等存储设备),在格式化成分区之后,就是一个文件系统了,但还是有很多空间可以被使用(如120G),此时超级块就是这个文件系统的一个使用目录,其实就是包含了很多的管理和存储空间登记的信息。fs_supers指向系统中相同文件系统的超级块对象的链表。
- get_sb:这是一个函数指针,依赖于具体的文件系统来实现,表示分配一个超级块对象并初始化或者读取一个已经存在的超级块对象。
- kill_sb:删除一个超级块对象。
- owner:指向实现文件的模块的指针,因为文件系统可以在源码中直接实现,也可以由模块来安装。
- 其它字段:其它的都是一些锁的字段。
三,文件系统的注册
以rootfs文件系统的注册为例,这个文件系统是在系统初始化期间注册的,调用路径如下:
asmlinkage void __init start_kernel(void){。。。。。。vfs_caches_init(num_physpages);。。。。。。}void __init vfs_caches_init(unsigned long mempages){。。。。。。mnt_init();。。。。。。}void __init mnt_init(void){。。。。。。init_rootfs();。。。。。。}int __init init_rootfs(void){int err;err = bdi_init(&ramfs_backing_dev_info);if (err)return err;err = register_filesystem(&rootfs_fs_type);if (err)bdi_destroy(&ramfs_backing_dev_info);return err;}rootfs文件系统的定义如下:
static struct file_system_type rootfs_fs_type = {.name= "rootfs",.get_sb= rootfs_get_sb,.kill_sb= kill_litter_super,};然后能过调用register_filesystem完成文件系统的注册,这个定义比较简单,作为另一个文件系统,定义如下:
static struct file_system_type ext2_fs_type = {.owner= THIS_MODULE,.name= "ext2",.get_sb= ext2_get_sb,.kill_sb= kill_block_super,.fs_flags= FS_REQUIRES_DEV,};
上面的结构实例就是EXT2文件系统,本文不讨论这个文件系统的注册过程,但终究肯定是调用register_filesystem函数完成注册。
int register_filesystem(struct file_system_type * fs){int res = 0;struct file_system_type ** p;BUG_ON(strchr(fs->name, '.'));if (fs->next)return -EBUSY;INIT_LIST_HEAD(&fs->fs_supers);write_lock(&file_systems_lock);p = find_filesystem(fs->name, strlen(fs->name));if (*p)res = -EBUSY;else*p = fs;write_unlock(&file_systems_lock);return res;}static struct file_system_type **find_filesystem(const char *name, unsigned len){ struct file_system_type **p; for (p=&file_systems; *p; p=&(*p)->next) if (strlen((*p)->name) == len && strncmp((*p)->name, name, len) == 0) break; return p;}上面的过程比较简单,就是从全局变量file_systems中找到相同的文件系统,如果已经存在文件系统,说明已经注册过该文件系统,如果链表中不存在,就将该文件加入到链表中完成文件系统的注册,所以注册过程就是将文件系统的数据结构加入到全局的链表中。
四,文件系统的卸载
卸载过程比较简单,调用unregister_filesystem函数完成:
int unregister_filesystem(struct file_system_type * fs){struct file_system_type ** tmp;write_lock(&file_systems_lock);tmp = &file_systems;while (*tmp) {if (fs == *tmp) {*tmp = fs->next;fs->next = NULL;write_unlock(&file_systems_lock);return 0;}tmp = &(*tmp)->next;}write_unlock(&file_systems_lock);return -EINVAL;}
这个过程就是将文件系统的数据结构实例从全局的链表中删除。
- 内核文件系统的注册
- 内核的文件系统的注册
- linux 文件系统模块的注册
- uclinux内核的文件系统类型
- Android内核的根文件系统
- Android内核的根文件系统
- Android内核的根文件系统
- Android内核的根文件系统
- 内核和文件系统的区别
- 内核与文件系统的关系
- 内核和文件系统的关系
- linux文件系统的系统分析--(二)文件系统类型的注册
- linux文件系统的系统分析--(二)文件系统类型的注册
- linux文件系统的系统分析--(二)文件系统类型的注册
- rootfs文件系统的注册和挂载
- linux内核探秘4---文件系统(最简单的文件系统aufs)
- 内核与根文件系统的联系
- 内核无法挂载根文件系统的原因总结
- HashMap,LinkedHashMap,TreeMap应用
- 黑马程序员 System类获取系统属性信息
- 解决如何使用Notepad++让代码高亮复制至word,网页问题
- 曾经狠幸福空间QQ日志-喜欢伤感,甚至颓废
- Linux学习笔记(十二)
- 内核的文件系统的注册
- Java容器类
- 抽象类和接口
- addChild()的区别addChildAt()
- 用…(rest) 来表示不确定个数的Arguments变量
- 检测操作系统
- 检测显示设置
- 数组
- 初识Socket