文件系统学习3 注册和加载 以及路径解析
2017-11-30 07:30
507 查看
文件系统注册
注册fs:国家允许开银行/国企/股份制公司,把他们的性质特征写在法律里面公开,大家可以查阅。
加载fs:开工商银行,神华公司等。需要登记公司地址和联系方式(mnt),法人(sb)等信息
加载,共有两个路径,都需要解析
全路径查找是核心
文件系统错误修复实例(1)
http://blog.csdn.net/ChuiGeDaQiQiu/article/details/24138875
卸载文件系统失败的时候可以通过fuser检查和杀死访问磁盘的进程
fuser命令详解(原创)
http://czmmiao.iteye.com/blog/1733722
e2fsprogs编译问题
http://blog.csdn.net/sanwenyublog/article/details/52817796
mount过程分析之六——挂载关系(图解)
http://blog.csdn.net/ZR_Lang/article/details/40343899
mount过程分析之七(do_add_mount)
http://blog.csdn.net/ZR_Lang/article/details/40325241
注册fs:国家允许开银行/国企/股份制公司,把他们的性质特征写在法律里面公开,大家可以查阅。
加载fs:开工商银行,神华公司等。需要登记公司地址和联系方式(mnt),法人(sb)等信息
module_init(init_ext3_fs) =>init_ext3_xattr(); =>init_inodecache(); =>register_filesystem(&ext3_fs_type);//如果在链表则返回,否则加入链表 static struct file_system_type ext3_fs_type = { .owner = THIS_MODULE, .name = "ext3", .get_sb = ext3_get_sb, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, };
加载,共有两个路径,都需要解析
sys_mount =>retval = do_mount((char *)dev_page, dir_page, (char *)type_page, flags, (void *)data_page); =>retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); =>do_path_lookup(AT_FDCWD, name, flags, nd);//加载的路径解析 =>if (*name=='/') ==>nd->mnt = mntget(fs->rootmnt); ==>nd->dentry = dget(fs->root); =>else if (dfd == AT_FDCWD) ==>nd->mnt = mntget(fs->pwdmnt); ==>nd->dentry = dget(fs->pwd); =>retval = path_walk(name, nd); } =>retval = do_new_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); =>struct vfsmount *mnt = do_kern_mount(type, flags, name, data); =>struct file_system_type *type = get_fs_type(fstype); =>struct vfsmount *mnt = vfs_kern_mount(type, flags, name, data);//3大功能 分配mnt;分配sb(如果没有分配的话);填充mnt基本信息 =>mnt = alloc_vfsmnt(name);//第一功能 =>error = type->get_sb(type, flags, name, data, mnt);//Super.c (c:\linux\linux-2.6.23\fs\ext2): .get_sb = ext2_get_sb,//第二功能 =>ext2_get_sb =>get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt); =>bdev = open_bdev_excl(dev_name, flags, fs_type); =>struct block_device *bdev = lookup_bdev(path); =>error = path_lookup(path, LOOKUP_FOLLOW, &nd); =>do_path_lookup(AT_FDCWD, name, flags, nd);//设备节点路径解析 =>inode = nd.dentry->d_inode; =>bdev = bd_acquire(inode); =>s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); =>if (s->s_root) close_bdev_excl(bdev);//如果已经有super block,那么不需要重新申请和填充 =>else sb_set_blocksize(s, block_size(bdev)); error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);//调用ext2_fill_super回调函数 =>sb_block = get_sb_block(&data);//默认是1,如果mount参数有sb=xxx则用用户参数,extx文件系统超级块有备份,默认超级块故障可以用备份超级块mount进行恢复 =>sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);//分配超级快 sb->s_fs_info = sbi; =>blocksize = sb_min_blocksize(sb, BLOCK_SIZE);//估算最小逻辑块大小,为读取超级块做准备 =>bh = sb_bread(sb, logic_sb_block)//读取超级块,结果放在bh磁盘高速缓存里面 =>es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);//解析ext2磁盘超级块,并将高速缓存的sb信息填充到sbi里面 sbi->s_es = es; sb->s_magic = le16_to_cpu(es->s_magic); =>for (i = 0; i < db_count; i++) block = descriptor_loc(sb, logic_sb_block, i); sbi->s_group_desc[i] = sb_bread(sb, block); =>sb->s_op = &ext2_sops;//赋值超级块的方法 sb->s_export_op = &ext2_export_ops; =>ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); =>mnt->mnt_mountpoint = mnt->mnt_root;//第三功能 mnt->mnt_parent = mnt; =>do_add_mount(mnt, nd, mnt_flags, NULL);//将mnt放到对应的一坨各种链表里面 =>while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry));//抽丝剥茧,找到堆叠的最底层的dentry,详见《mount过程分析之七(do_add_mount)》 =>err = graft_tree(newmnt, nd))//加入链表
全路径查找是核心
static int fastcall path_walk(const char * name, struct nameidata *nd) =>link_path_walk(name, nd); =>result = __link_path_walk(name, nd); =>inode = nd->dentry->d_inode; 4000 =>for(;;) //每一次循环,剥离一层目录,通过hash抽丝剥茧找到以此找到下一个entry ==>this.name = name;//初始化hash和剥离出/~/之间的第一个name字符串,指向起始地址,通过len决定长度 c = *(const unsigned char *)name; hash = init_name_hash(); do { name++; hash = partial_name_hash(c, hash); c = *(const unsigned char *)name; } while (c && (c != '/')); this.len = name - (const char *) this.name;//this.len等于两个/之间的长度,即一个目录 this.hash = end_name_hash(hash); ==>nd->dentry->d_op->d_hash(nd->dentry, &this);//如果fs有私有hash,则选用私有hash,这个是dentry的方法 ==>do_lookup(nd, &this, &next); =>struct dentry *dentry = __d_lookup(nd->dentry, name); =>dentry = real_lookup(nd->dentry, name, nd); =>result = d_lookup(parent, name); =>struct hlist_head *head = d_hash(parent,hash); =>hlist_for_each_entry_rcu(dentry, node, head, d_hash)//命中哈希后,在哈希的链表里面遍历 ==>qstr = &dentry->d_name;//匹配entry,如果有私有的方法,则用私有,这个是dentry的方法,否则字符串匹配 if (parent->d_op && parent->d_op->d_compare) { if (parent->d_op->d_compare(parent, qstr, name)) goto next; } else { if (qstr->len != len) goto next; if (memcmp(qstr->name, str, len)) goto next; } ==>found = dentry;//找到则返回 =>if (!result)//如果缓存没有找到,则需要从磁盘高速缓存读取 ==>result = dir->i_op->lookup(dir, dentry, nd);//inode的方法 =>ext2_lookup =>ino = ext2_inode_by_name(dir, dentry); =>struct ext2_dir_entry_2 * de = ext2_find_entry (dir, dentry, &page); =>do { page = ext2_get_page(dir, n); =>page = read_mapping_page(mapping, n, NULL); =>filler_t *filler = (filler_t *)mapping->a_ops->readpage; =>return read_cache_page(mapping, index, filler, data); =>page = read_cache_page_async(mapping, index, filler, data); =>page = __read_cache_page(mapping, index, filler, data); =>page = find_get_page(mapping, index);//读磁盘高速缓存,否则分配page,通过fill回调函数读取磁盘刷新page =>if (!page) if (!cached_page) cached_page = page_cache_alloc_cold(mapping); =>page = cached_page; =>err = filler(data, page); =>err = filler(data, page); }//do =>inode = iget(dir->i_sb, ino); =>sb->s_op->read_inode(inode);//.read_inode = ext2_read_inode, =>struct ext2_inode * raw_inode = ext2_get_inode(inode->i_sb, ino, &bh);//高速缓存读取ext2_inode节点 =>将读取的raw_inode信息赋值给inode内存模型 =>d_splice_alias(inode, dentry); ==>if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link) ====>err = do_follow_link(&next, nd); ====>inode = nd->dentry->d_inode; ==>else ====>path_to_nameidata(&next, nd); =>nd->mnt = path->mnt; nd->dentry = path->dentry;
文件系统错误修复实例(1)
http://blog.csdn.net/ChuiGeDaQiQiu/article/details/24138875
卸载文件系统失败的时候可以通过fuser检查和杀死访问磁盘的进程
fuser命令详解(原创)
http://czmmiao.iteye.com/blog/1733722
e2fsprogs编译问题
http://blog.csdn.net/sanwenyublog/article/details/52817796
mount过程分析之六——挂载关系(图解)
http://blog.csdn.net/ZR_Lang/article/details/40343899
mount过程分析之七(do_add_mount)
http://blog.csdn.net/ZR_Lang/article/details/40325241
相关文章推荐
- PHP之文件系统处理_解析目录路径
- Log4j配置文件解析以及加载自己的配置文件
- “未能加载文件或程序集“AspNetPager”或它的某一个依赖项。系统找不到指定的路径。”的解决方法
- [文件系统]文件系统学习笔记(一)---基本概念以及inode
- 工作中常用到的linux命令二 c++系统环境配置 动态库文件路径的加载
- Log4j配置文件解析以及加载自己的配置文件
- Linux学习之CentOS(三)--初识linux的文件系统以及用户组等概念
- ios开发学习- 简易音乐播放器2 (基于iPhone4s屏幕尺寸)-- 歌词解析--plist文件应用--imageNamed图片加载耗内存
- android Uri利用及解析(文件操作)以及与路径的相互转换
- Log4j配置文件解析以及加载自己的配置文件
- Java学习笔记(二十二):Java 文件操作 :系统找不到指定的路径
- 学习三层模式中遇到未能加载文件或程序集“Adtion.DAL.SqlServer”……”的原因和解析
- 实践中学习vim之vim配置文件、插件文件加载路径
- 使用import简化spring的配置 spring import 标签的解析 使用import或加载spring配置时,报错误There is no ID/IDREF 多个Spring配置文件import resource路径配置
- Log4j配置文件解析以及加载自己的配置文件
- RedHat6.5 puppet配置(四)- 默认路径下的文件以及puppet命令解析
- 云计算学习笔记004---hadoop的简介,以及安装,用命令实现对hdfs系统进行文件的上传下载
- 用系统命令加载磁盘 (隐藏文件) "学习资料"放的再深也不怕
- 安装、进程-云计算学习笔记---hadoop的简介,以及安装,用命令实现对hdfs系统进行文件的上传下载-by小雨
- 在 Android 系统中直接调用 SO文件(包含System.loadLibrary加载so的路径解释)