原文链接http://bbs.chinaunix.net/viewthread.php?tid=2054087&page=1&authorid=61059
1楼 发表于 2008-05-23 16:30 | 显示全部帖子
1楼 发表于 2008-05-23 16:30 | 显示全部帖子
第 37 ~ 39 楼更新了mount 文件系统部分的笔记。 - 2009.03.19. --------------------------------------------------------------------------------------- 采用主要以图表的方式表达,这样感觉很直观. super block 相关的数据结构为: struct super_block { struct list_head s_list; /* Keep this first */ 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; 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; 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_inodes; /* all inodes */ 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_id[32]; /* 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 */ /* Granuality of c/m/atime in ns. Cannot be worse than a second */ u32 s_time_gran; }; super_block存在于两个链表中,一个是系统所有super_block的链表, 一个是对于特定的文件系统的super_block链表. 所有的super_block都存在于 super-blocks 链表中: 对于特定的文件系统, 该文件系统的所有的super block 都存在于file_sytem_type中的fs_supers链表中. 而所有的文件系统,都存在于file_systems链表中.这是通过调用register_filesystem接口来注册文件系统的. int register_filesystem(struct file_system_type * fs) [ 本帖最后由 xpl 于 2009-3-19 15:58 编辑 ] |
__________________________________
http://blog.sina.com.cn/bytex
------------------------------------------------------------------------------
http://blog.sina.com.cn/bytex
------------------------------------------------------------------------------
回复 #1 xpl 的帖子
2. inode 相关的数据结构为: struct inode { struct hlist_node i_hash; struct list_head i_list; struct list_head i_sb_list; struct list_head i_dentry; unsigned long i_ino; atomic_t i_count; umode_t i_mode; unsigned int i_nlink; uid_t i_uid; 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; 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 */ 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_dquot[MAXQUOTAS]; #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; #ifdef CONFIG_DNOTIFY unsigned long i_dnotify_mask; /* Directory notify events */ struct dnotify_struct *i_dnotify; /* for directory notifications */ #endif 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; #endif }; inode存在于两个双向链表中: 一个是inode所在文件系统的super block的 s_inodes 链表中 一个是根据inode的使用状态存在于以下三个链表中的某个链表中: 1. 未用的: inode_unused 链表 2. 正在使用的: inode_in_use 链表 3. 脏的: super block中的s_dirty 链表 另外,还有一个重要的链表: inode_hashtable(这个暂不介绍). |
__________________________________
http://blog.sina.com.cn/bytex
--------------------------------------------------------------------------------
http://blog.sina.com.cn/bytex
--------------------------------------------------------------------------------
3. dentry 相关的数据结构为: struct dentry { atomic_t d_count; unsigned int d_flags; /* protected by d_lock */ spinlock_t d_lock; /* per dentry lock */ 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 qstr d_name; 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; struct super_block *d_sb; /* The root of the dentry tree */ void *d_fsdata; /* fs-specific data */ 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_iname[DNAME_INLINE_LEN_MIN]; /* small names */ }; dentry对象存在于三个双向链表中: 所有未用的目录项: dentry_unused 链表 正在使用的目录项: 对应inode的 i_dentry 链表 表示父子目录结构的链表 另外,还有一个重要的链表: inode_hashtable(这个暂不介绍). |
__________________________________
http://blog.sina.com.cn/bytex
-------------------------------------------------------------------------------------
1
http://blog.sina.com.cn/bytex
-------------------------------------------------------------------------------------
4. 进程相关的信息 和进程相关的信息, 涉及到四个重要的数据结构: file, fs_struct, files_struct 和 namespace 相关的数据结构为: struct file { struct list_head f_list; struct dentry *f_dentry; struct vfsmount *f_vfsmnt; struct file_operations *f_op; atomic_t f_count; unsigned int f_flags; mode_t f_mode; int f_error; loff_t f_pos; struct fown_struct f_owner; unsigned int f_uid, f_gid; struct file_ra_state f_ra; size_t f_maxcount; unsigned long f_version; void *f_security; /* needed for tty driver, and maybe others */ void *private_data; #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links; spinlock_t f_ep_lock; #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; }; ------------------------------------------------------------------------------- struct fs_struct { atomic_t count; rwlock_t lock; int umask; struct dentry * root, * pwd, * altroot; struct vfsmount * rootmnt, * pwdmnt, * altrootmnt; }; ------------------------------------------------------------------------------- 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 */ fd_set *close_on_exec; fd_set *open_fds; fd_set close_on_exec_init; fd_set open_fds_init; struct file * fd_array[NR_OPEN_DEFAULT]; }; ------------------------------------------------------------------------------- struct namespace { atomic_t count; struct vfsmount * root; struct list_head list; struct rw_semaphore sem; }; 每个进程都有自己的namespace. fs_struct用于表示进程与文件系统之间的结构关系,比如当前的工作目录,进程的根目录等等. files_struct 用于表示当前进程打开的文件. 而对于每一个打开的文件,由file对象来表示. Linux中,常常用文件描述符(file descriptor)来表示一个打开的文件,这个描述符的值往往是一个大于或等于0的整数. 而这个整数,其实就是在files_struct中file数组fd的下标. 对于所有打开的文件, 这些文件描述符会存储在open_fds的位图中. |
__________________________________
http://blog.sina.com.cn/bytex
------------------------------------------------------------------------------------
http://blog.sina.com.cn/bytex
mount 文件系统 主要数据结构: struct namespace { atomic_t count; /* 引用技术 */ struct vfsmount * root; /* 根目录的 vfsmount */ struct list_head list; /* 所有已经mount的 文件系统的 list */ struct rw_semaphore sem; /* 读写信号量 */ }; struct vfsmount { struct list_head mnt_hash; /* 用于散列表的list */ struct vfsmount *mnt_parent; /* 指向父文件系统的 vfsmount */ struct dentry *mnt_mountpoint; /* mountpoint 的 dentry */ struct dentry *mnt_root; /* mount的文件系统的根目录的 dentry */ struct super_block *mnt_sb; /* 指向该文件系统的 superblock */ struct list_head mnt_mounts; /* 所有mount到该文件系统的 vfsmount 的 list */ struct list_head mnt_child; /* 子文件系统的 list */ atomic_t mnt_count; /* 引用计数 */ int mnt_flags; /* mount 的 flag */ int mnt_expiry_mark; /* 到期标志 */ char *mnt_devname; /* mount设备的名称 比如: /dev/dsk/hda1 */ struct list_head mnt_list; /* 在namespace上的vfsmount的 list */ struct list_head mnt_fslink; struct namespace *mnt_namespace; /* 指向mount文件系统的进程的 namespace */ }; struct nameidata { struct dentry *dentry; /* 目录的dentry */ struct vfsmount *mnt; /* 目录所在的文件系统的 vfsmount */ struct qstr last; /* 在LOOKUP_PARENT 标志被设置时使用,存储路径中最后一个分量 */ unsigned int flags; /* 查找的 flags */ int last_type; /* 在LOOKUP_PARENT 标志被设置时使用,存储路径名的最后一个分量的类型,值见下面的enum */ unsigned depth; /* 符号链接的嵌套深度 */ char *saved_names[MAX_NESTED_LINKS + 1]; /* 存储嵌套的符号链接所关联的路径名数组, 通过depth作为下标来索引 */ /* Intent data */ union { struct open_intent open; } intent; }; /* * Type of the last component on LOOKUP_PARENT */ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; /* nameidata 的 last_type 的值 */ /* * The bitmask for a lookup event: * - follow links at the end * - require a directory * - ending slashes ok even for nonexistent files * - internal "there are more path compnents" flag * - locked when lookup done with dcache_lock held * - dentry cache is untrusted; force a real lookup */ #define LOOKUP_FOLLOW 1 #define LOOKUP_DIRECTORY 2 #define LOOKUP_CONTINUE 4 #define LOOKUP_PARENT 16 #define LOOKUP_NOALT 32 #define LOOKUP_REVAL 64 /* * Intent data */ #define LOOKUP_OPEN (0x0100) #define LOOKUP_CREATE (0x0200) #define LOOKUP_ACCESS (0x0400) /* * "quick string" -- eases parameter passing, but more importantly * saves "metadata" about the string (ie length and the hash). * * hash comes first so it snuggles against d_parent in the * dentry. */ struct qstr { unsigned int hash; /* hash值 */ unsigned int len; /* 路径中分量名称的长度 */ const unsigned char *name; /* 路径中分量名称的字符串地址 */ }; -------------------------------------------------------------------------- 需要补习的内容: 对于一个文件(在Linux下所有都是文件,包括目录等等) ,如何判断该文件 是不是目录,或者是不是符号链接, 是通过inode : 如果是目录,则一定有 inode->i_op->lookup 方法, 即 inode->i_op->lookup 一定不是NULL 如果是符号链接, 则一定有 inode->i_op->follow_link 方法,即 inode->i_op->follow_link 一定不是NULL -------------------------------------------------------------------------- 对于每一个 mount 的文件系统,都由一个 vfsmount 实例来表示。 对于每一个进程,都有自己的 namespace , 这可以理解为这个进程的地盘。 在这里,所有的文件系统都要挂上来统一管理, 如下所示: 图(1) 同时,对于所有的vfsmount,都存在于 一个hash table中,他们通过一个 hash 数组组织在一起: 图(2) 对于mount的文件系统,会有在一个文件系统上 mount 另外一个文件系统的情况,这种情况,可以称原文件系统为 父vfsmount, 对于mount上的文件系统,称之位子文件系统。 他们的关系如下: 图(3) 下面我以一个例子来说明: 例如我们要mount一个设备 /dev/hdb1 到 /home/xpl 目录下 我们假设 /home/xpl 就是当前进程的根文件系统中的目录(即 home 和 xpl 都没有mount任何文件系统), 我们mount的时候,传入的参数有三个: 要mount的设备( /dev/hdb1 ) , 设备的文件系统 ( ext2 之类的), mount到什么目录 ( /home/xpl ) 首先,我们要根据要mount的目录的路径名( 我们传入的只是路径名称的字符串),来找到mount的目录 disk 的dentry (即 mountpoint ) 这个查找过程如下所示: 1. 首先确定查找路径的起始目录,要么是根目录,要么是当前目录。 如果是根目录,则根目录的 dentry 和 vfsmount 的信息在: current->fs->root 和 current->fs->rootmnt 如果是当前目录,则当前目录的 dentry 和 vfsmount 的信息在:current->fs->pwd 和 current->fs->pwdmnt 2. 然后,从路径的起始目录开始逐级的往下找。 对于我们的例子,我们首先要查找根目录下的 home 目录( 就是要找到 home 目录的 dentry 和 vfsmount 对象) 1) 首先在 hashtable 中查找,就是在上面的图(2)中的链表中找。 2) 如果这个目录没有在 hashtable 中,则需要到磁盘上(我们假设根文件系统是在一个磁盘上,如果不是,就是去根文件系统对应的存储介质中查找)去查找 这通过调用 根目录的 inode 的 lookup 方法来查找。 通过根目录的 dentry->d_inode 得到根目录的inode,然后调用 inode->i_ops->lookup 方法,将要查找目录的名称作为参数传递进去。 3. 找到了第一个目录,下面的过程就是简单的递归了,最后,找到 目录 xpl 的 dentry 和 vfsmount |
评分人数
- scutan: 精品文章可用积分 + 10
__________________________________
http://blog.sina.com.cn/bytex
http://blog.sina.com.cn/bytex
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(616) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
评论热议