




已阅读5页,还剩51页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
linux文件系统之路径查找与文件系统的挂载- 本文系本站原创,欢迎转载!转载请注明出处:/-文件系统是操作系统的一个重要的功能,linux提供了对各种文件系统的支持,具有极高的扩展性.文件系统这一部份也是linux内核中难以理 解的一部份,因为它与很多子系统有关.有时候还需要涉及到具体的磁盘分区格式.下面的代码分析以ext2格式为基础进行分析.在分析的过程中会遇到了块设 备操作的一些API,暂且将它放至一边。块设备的操作会以单独的专题做讨论。一:与关系统有关的数据结构1.1:VFS相关的数据结构在文件系统中,涉及到最多的就是super_block,inode,dentry这几个结构。先列出这几个结构中各成员所代表的含义,具体的作用等到代码遇到再进行分析。这几个结构在内核中的定义如下:struct super_block /用来形成一个链表 struct list_head s_list; /* Keep this first */ /super_block所对应的设备 dev_t s_dev; /* search index; _not_ kdev_t */ /以字节为单位的块大小 unsigned long s_blocksize; unsigned long s_old_blocksize; /以位为单位的块大小 unsigned char s_blocksize_bits; /“脏”标志 unsigned char s_dirt; /文件大小的上限 unsigned long long s_maxbytes; /* Max file size */ /所属的文件系统 struct file_system_type *s_type; /super_block的操作 struct super_operations *s_op; /磁盘限额的方法 struct dquot_operations *dq_op; /配置磁盘限额的方法 struct quotactl_ops *s_qcop; /导出的方法 struct export_operations *s_export_op; /所对应的标志 unsigned long s_flags; /文件系统的魔数 unsigned long s_magic; /目录登录点 struct dentry *s_root; /为避免竞争,所用的rw_semaphore struct rw_semaphore s_umount; struct semaphore s_lock; int s_count; /文件系统的同步标志 int s_syncing; /尚末将文件系统同步 int s_need_sync_fs; /活动引用计数 atomic_t s_active; /安全模块 void *s_security; struct xattr_handler *s_xattr; /脏节点链表 struct list_head s_dirty; /* dirty inodes */ /回写链表 struct list_head s_io; /* parked for writeback */ /匿名分区 struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ /被分区的文件链表 struct list_head s_files; /相关的块设备 struct block_device *s_bdev; /该类型的文件系统 struct list_head s_instances; struct quota_info s_dquot; /* Diskquota specific options */ /如果该标志被置位,则禁止使用该文件系统(可能需要等待某些操作的完成,例如同步) int s_frozen; /等待队列 wait_queue_head_t s_wait_unfrozen; /设备的名称 char s_id32; /* Informational name */ /指向特定的文件系统的信息(这个是一个统一的结构,毕竟不同的文件系统有很多不同的信息) void *s_fs_info; /* Filesystem private info */ /* * The next field is for VFS *only*. No filesystems have any business * even looking at it. You had been warned. */ /删除时使用的信号量 struct semaphore s_vfs_rename_sem; /* Kludge */struct inode /散列表 struct hlist_node i_hash; /用来形成链表 struct list_head i_list; /目录项链表 struct list_head i_dentry; /索引节点号 unsigned long i_ino; /引用计数 atomic_t i_count; /访问权根控制 umode_t i_mode; /硬链接数目 unsigned int i_nlink; /使用者id uid_t i_uid; /使用者的gid gid_t i_gid; /所属的设备 dev_t i_rdev; /以字节为单位的文件大小 loff_t i_size; /最后访问时间 struct timespec i_atime; /最后修改时间 struct timespec i_mtime; /最后改变时间 struct timespec i_ctime; /以位为单位的块大小 unsigned int i_blkbits; /以字节为单位的块大小 unsigned long i_blksize; /版本号 unsigned long i_version; /文件的块数 unsigned long i_blocks; /使用的字节数 unsigned short i_bytes; /如果该成员被置为1则这个inode表示的是一个套接字 unsigned char i_sock; /索引结点的自旋锁 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ /索引结点的信号量 struct semaphore i_sem; struct rw_semaphore i_alloc_sem; /索引结点的操作列表 struct inode_operations *i_op; /索引结点所属文件的操作列表 struct file_operations *i_fop; /* former -i_op-default_file_ops */ /索引结点的所属super_block struct super_block *i_sb; /文件锁链表 struct file_lock *i_flock; /把向所属的页面缓存 struct address_space *i_mapping; struct address_space i_data;#ifdef CONFIG_QUOTA struct dquot *i_dquotMAXQUOTAS;#endif /* These three should probably be a union */ /块设备链表 struct list_head i_devices; /管道信息 struct pipe_inode_info *i_pipe; /所属块设备 struct block_device *i_bdev; /所属的字符设备 struct cdev *i_cdev; int i_cindex; /索引结点的版本号 _u32 i_generation; /目录通知掩码 unsigned long i_dnotify_mask; /* Directory notify events */ /目录通知 struct dnotify_struct *i_dnotify; /* for directory notifications */ /状态标志 unsigned long i_state; /首次修改时间 unsigned long dirtied_when; /* jiffies of first dirtying */ /文件系统标志 unsigned int i_flags; /写者计数 atomic_t i_writecount; /安全模块 void *i_security; /文件的特殊信息 union void *generic_ip; u;#ifdef _NEED_I_SIZE_ORDERED seqcount_t i_size_seqcount;#endifstruct dentry /引用计数 atomic_t d_count; /目录项标识 unsigned int d_flags; /* protected by d_lock */ /单目录项 spinlock_t d_lock; /* per dentry lock */ /相关的inode struct inode *d_inode; /* Where the name belongs to - NULL is * negative */ /* * The next three fields are touched by _d_lookup. Place them here * so they all fit in a 16-byte range, with 16-byte alignment. */ /父目录中的目录结构 struct dentry *d_parent; /* parent directory */ /散队表头 struct hlist_head *d_bucket; /* lookup hash bucket */ /目录项的名字 struct qstr d_name; /LRU链表 struct list_head d_lru; /* LRU list */ /父目录的子目录链表 struct list_head d_child; /* child of parent list */ /目录的子目录链表 struct list_head d_subdirs; /* our children */ /索引结点的别名链表 struct list_head d_alias; /* inode alias list */ /重新生效的时间 unsigned long d_time; /* used by d_revalidate */ /目录项的操作列表 struct dentry_operations *d_op; /目录项的所属super_block struct super_block *d_sb; /* The root of the dentry tree */ void *d_fsdata; /* fs-specific data */ void * d_extra_attributes; /* TUX-specific data */ /RCU锁 struct rcu_head d_rcu; struct dcookie_struct *d_cookie; /* cookie, if any */ /所属散列表 struct hlist_node d_hash; /* lookup hash list */ /是否有文件系统被挂载到此目录下 int d_mounted; /短文件名 unsigned char d_inameDNAME_INLINE_LEN_MIN; /* small names */在这里要注意的是,不管目录还是普通文件在文件系统中都是对应的文件,只是文件的类型不一样,都有一个dentry项,dentry项对应一个inode.inode和dentry都有一个成员指向文件系统的super_block.1.2:与进程相关的结构在task的定义中,包含两个成员:fs,file .它们的结构定义如下所示:struct fs_struct /结构的引用计数 atomic_t count; /读写锁 rwlock_t lock; /默认的文件访问权限 int umask; /用户的root目录,当前目录,与替换目录 struct dentry * root, * pwd, * altroot; /root目录,当前目录与替换目录所对应的文件系统 struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;其中,在x86平台中,altroot与altrootmnt的值为空.File对应的数据结构为files_struct.它的结构定义如下:struct files_struct /结构体的使用计数 atomic_t count; spinlock_t file_lock; /* Protects all the below members. Nests inside tsk-alloc_lock */ /文件对象数的上限 int max_fds; /文件描述符的上限 int max_fdset; /下一个文件描述符 int next_fd; /全部文件对象数组 struct file * fd; /* current fd array */ /exec()关闭的文件描述符 fd_set *close_on_exec; /打开的文件描述符指针 fd_set *open_fds; /exe()关闭的初始化文件 fd_set close_on_exec_init; /文件描述符的初始集合 fd_set open_fds_init; /默认的文件对象数组 struct file * fd_arrayNR_OPEN_DEFAULT;二:路径名的查找在应用中,经常有为给定的路径寻找结点的操作,例如cd /home/eric/kernel_study.这个操作是经常需用用到的操作,在进行深入的文件系统学习前,有必要先了解一下这个操作的实现.在内核中,path_lookup()用来查到一个给定路径的所属文件结点。它的代码如下:int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) int retval; /刚开始搜索前,将nd-last_type置为LAST_ROOT nd-last_type = LAST_ROOT; /* if there are only slashes. */ nd-flags = flags; nd-depth = 0; /为了避免对current-fs的读写竞争,先加锁 read_lock(¤t-fs-lock); /第一个路径字符为/,表示的是一个绝对路径.eg :/home/eric if (*name=/) /在x86中,task-fs-altroot为空 if (current-fs-altroot & !(nd-flags & LOOKUP_NOALT) nd-mnt = mntget(current-fs-altrootmnt); nd-dentry = dget(current-fs-altroot); read_unlock(¤t-fs-lock); if (_emul_lookup_dentry(name,nd) return 0; read_lock(¤t-fs-lock); /将搜索的起始路径设为root nd-mnt = mntget(current-fs-rootmnt); nd-dentry = dget(current-fs-root); else /相对路径.eg: eric/kernel_study /将搜综的起始路径设为pwd nd-mnt = mntget(current-fs-pwdmnt); nd-dentry = dget(current-fs-pwd); /解锁 read_unlock(¤t-fs-lock); /将当前进程的total_link_count置为0(表示末遇到链接) current-total_link_count = 0; retval = link_path_walk(name, nd); if (unlikely(current-audit_context & nd & nd-dentry & nd-dentry-d_inode) audit_inode(name, nd-dentry-d_inode-i_ino, nd-dentry-d_inode-i_rdev); return retval;这个函数有三个参数:name表示路径的字符串。Flag表示搜索的标志.如下所示:/如果最后一个结点是符号链表,跟随进去#define LOOKUP_FOLLOW 1/最后的结点需要是一个目录#define LOOKUP_DIRECTORY 2/继续往下面搜索#define LOOKUP_CONTINUE 4/搜索最后结点的父目录#define LOOKUP_PARENT 16/不要搜索替换目录,在x86中没有使用#define LOOKUP_NOALT 32/在搜索的过程中不能被打断,#define LOOKUP_ATOMIC 64/* Intent data*/搜索文件的目的#define LOOKUP_OPEN (0x0100)#define LOOKUP_CREATE (0x0200)#define LOOKUP_ACCESS (0x0400)最后的一参数nameidata用来存放中间信息和搜索的结果.它的结构如下:/存储搜索路径过程中的信息struct nameidata /存放最后一次搜索的dentry struct dentry *dentry; /存放dentry所属的文件系统 struct vfsmount *mnt; /最后搜索的结点的名称 struct qstr last; /标志,与path_lookup()中的flag参数相同 unsigned int flags; /最后一次搜索的类型 int last_type; /搜索的链接深度 unsigned depth; char *saved_namesMAX_NESTED_LINKS + 1; /* Intent data */ union struct open_intent open; intent;上述代码会判断是一个相对路径还是绝对路径。将其信息设置在nd-dentry和nd-vfsmount中后转入link_path_walk()进行搜索.代码如下所示:int fastcall link_path_walk(const char * name, struct nameidata *nd) struct path next; struct inode *inode; int err, atomic; unsigned int lookup_flags = nd-flags; /如果搜索标志中含有LOOKUP_ATOMIC. atomci等于1 atomic = (lookup_flags & LOOKUP_ATOMIC); /跳过路径前面的/ while (*name=/) name+; /如果后面没有数据了,说明已经搜索完了. if (!*name) goto return_reval; /搜索目录所对应的inode inode = nd-dentry-d_inode; /如果nd-depth被置位,则定义lookup_flags = LOOKUP_FOLLOW if (nd-depth) lookup_flags = LOOKUP_FOLLOW; /* At this point we know we have a real path component. */ for(;) unsigned long hash; struct qstr this; unsigned int c; /判断是否有相应的权限 err = exec_permission_lite(inode, nd); if (err = -EAGAIN) err = permission(inode, MAY_EXEC, nd); if (err) break; /将结点的信息保存在this中.例如 : eric/kerne_study/fs /就会将eric保存到this中 = name; c = *(const unsigned char *)name; hash = init_name_hash(); /计算结点名称对应的hash值。一直到字符为空或者到了节点末尾为止(节点节尾,即遇上了/) do name+; hash = partial_name_hash(c, hash); c = *(const unsigned char *)name; while (c & (c != /); this.len = name - (const char *) ; this.hash = end_name_hash(hash); /* remove trailing slashes? */ /!c:则到了最后一个结点,且不以/结尾 eg: /home/eric if (!c) goto last_component; while (*+name = /); if (!*name) /最后一个结点是以/结尾的 eg:/home/eric/ goto last_with_slashes; /* * . and . are special - . especially so because it has * to be able to know about the current root directory and * parent relationships. */ /如果结点是以. 开头 /在linux中,.表示当前目录。.表示上一次目录 if (0 = .) switch (this.len) default: break; case 2: if (1 != .) break; follow_dotdot(&nd-mnt, &nd-dentry); inode = nd-dentry-d_inode; /* fallthrough */ case 1: / . continue; /* * See if the low-level filesystem might want * to use its own hash. */ /如果自定义哈希值计算 if (nd-dentry-d_op & nd-dentry-d_op-d_hash) err = nd-dentry-d_op-d_hash(nd-dentry, &this); if (err flags |= LOOKUP_CONTINUE; /* This does the actual lookups. */ /到nd-dentry中查找this. 如果有相应的结点,则将结点对应的denty存进next中 err = do_lookup(nd, &this, &next, atomic); /如果查找失败 if (err) break; /* Check mountpoints. */ /对于目录有文件系统挂载的处理 follow_mount(&next.mnt, &next.dentry); err = -ENOENT; /对查找节点节点的inode进行检查 inode = next.dentry-d_inode; if (!inode) goto out_dput; err = -ENOTDIR; if (!inode-i_op) goto out_dput; /如果该节点是一个链接 if (inode-i_op-follow_link) mntget(next.mnt); err = do_follow_link(next.dentry, nd); dput(next.dentry); mntput(next.mnt); if (err) goto return_err; err = -ENOENT; inode = nd-dentry-d_inode; if (!inode) break; err = -ENOTDIR; if (!inode-i_op) break; else /否则,释放nd-dentry。将next中的相应值赋给nd dput(nd-dentry); nd-mnt = next.mnt; nd-dentry = next.dentry; err = -ENOTDIR; /如果该结点没有定义lookup操作 if (!inode-i_op-lookup) break; /继续下一个节点的查找 continue; /* here ends the main loop */最后的结点是以/ 结尾last_with_slashes: /添加LOOKUP_FOLLOW | LOOKUP_DIRECTORY标志 lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;/最后的结点 last_component: nd-flags &= LOOKUP_CONTINUE; /如果定义了LOOKUP_PARENT:不必要搜索最后的结点,直接返回。那返回nameidata /包含的是父目录的相关信息 if (lookup_flags & LOOKUP_PARENT) goto lookup_parent; /如果没有定义LOOKUP_PARENT:则还需要解析最后的一个结点 if (0 = .) switch (this.len) default: break; case 2: if (1 != .) break; follow_dotdot(&nd-mnt, &nd-dentry); inode = nd-dentry-d_inode; /* fallthrough */ case 1: goto return_reval; if (nd-dentry-d_op & nd-dentry-d_op-d_hash) err = nd-dentry-d_op-d_hash(nd-dentry, &this); if (err d_inode; if (lookup_flags & LOOKUP_FOLLOW) & inode & inode-i_op & inode-i_op-follow_link) mntget(next.mnt); err = do_follow_link(next.dentry, nd); dput(next.dentry); mntput(next.mnt); if (err) goto return_err; inode = nd-dentry-d_inode; else dput(nd-dentry); nd-mnt = next.mnt; nd-dentry = next.dentry; err = -ENOENT; if (!inode) break; if (lookup_flags & LOOKUP_DIRECTORY) err = -ENOTDIR; if (!inode-i_op | !inode-i_op-lookup) break; goto return_base;lookup_parent: nd-last = this; /根据最后结点的名字。返回不同的last_type nd-last_type = LAST_NORM; if (0 != .) goto return_base; if (this.len = 1) nd-last_type = LAST_DOT; else if (this.len = 2 & 1 = .) nd-last_type = LAST_DOTDOT; else goto return_base;return_reval: /* * We bypassed the ordinary revalidation routines. * We may need to check the cached dentry for staleness. */ if (nd-dentry &
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 铁路改造工程环境影响报告书
- 2025年中国初级阅读真题及答案
- 新能源电池隔板加工制造项目建筑工程方案
- 高端医药中间体生产线建设项目技术方案
- 河北数学单招真题及答案
- 技术服务合同写作样式
- 光明区2024-2025学年第二学期三年级英语期末学业展示试卷及答案
- 商业办公空间租赁制式合同(含装修权属约定)
- 离婚后子女抚养责任及财产分割补充协议
- 棕榈油种植基地租赁合同范本:油脂加工与品牌合作
- MOOC 模拟电子电路实验-东南大学 中国大学慕课答案
- 多格列艾汀使用指南2024课件
- MOOC 创业基础-暨南大学 中国大学慕课答案
- GB/T 41666.4-2024地下无压排水管网非开挖修复用塑料管道系统第4部分:原位固化内衬法
- 云端药历健保署电子病历-慈济大学医学资讯学系
- 道路车辆 局域互联网络(LIN) 第3部分:协议规范
- 客户反馈管理方案处理客户反馈的有效举措
- 桩基工程施工总体部署
- 电梯故障分析报告
- 《春》专题探究课件(朗读的重音和停连)
- 电能质量技术监督培训课件
评论
0/150
提交评论