linux内核分析笔记----虚拟文件系统(下)
来源:互联网 发布:肯德基 网络市场调研 编辑:程序博客网 时间:2024/05/17 22:28
3.目录项对象.目录项的概念上节已经说了,我就不多说.目录项中也可包括安装点.在路径/mnt/cdrom/foo中,/,mnt,cdrom都属于目录项对象。目录项由dentry结构体表示,定义在文件linux/dcache.h中,描述如下:
struct
dentry {
atomic_t d_count;
/* usage count */
unsigned
long
d_vfs_flags;
/* dentry cache flags */
spinlock_t d_lock;
/* per-dentry lock */
struct
inode *d_inode;
/* associated inode */
struct
list_head d_lru;
/* unused list */
struct
list_head d_child;
/* list of dentries within */
struct
list_head d_subdirs;
/* subdirectories */
struct
list_head d_alias;
/* list of alias inodes */
unsigned
long
d_time;
/* revalidate time */
struct
dentry_operations *d_op;
/* dentry operations table */
struct
super_block *d_sb;
/* superblock of file */
unsigned
int
d_flags;
/* dentry flags */
int
d_mounted;
/* is this a mount point? */
void
*d_fsdata;
/* filesystem-specific data */
struct
rcu_head d_rcu;
/* RCU locking */
struct
dcookie_struct *d_cookie;
/* cookie */
struct
dentry *d_parent;
/* dentry object of parent */
struct
qstr d_name;
/* dentry name */
struct
hlist_node d_hash;
/* list of hash table entries */
struct
hlist_head *d_bucket;
/* hash bucket */
unsigned
char
d_iname[DNAME_INLINE_LEN_MIN];
/* short name */
};
由于目录项并非真正保存在磁盘上,所有目录项没有对应的磁盘数据结构,VFS根据字符串形式的路径名现场创建它,目录项结构体也没有是否被修改的标志。目录项对象有三种状态:被使用,未被使用和负状态。一个被使用的目录项对应一个有效的索引节点(即d_inode指向相应的索引节点)并且该对象存在一个或多个使用者(即d_count为正值)。一个未被使用的目录项对应一个有效的索引节点(d_inode指向一个索引节点),但是VFS当前并未使用它(d_count为0)。该目录项对象仍然指向一个有效对象,而且被保留在内存中以便需要时再使用它。显然这样要比重新创建要效率高些。一个负状态的目录项没有对应的有效索引节点(d_inode为NULL).因为索引节点已被删除了,或路径不再正确了,但是目录项仍然保留,以便快速解析以后的路径查询。虽然负的状态目录项有些用处,但如果需要的话话,还是可以删除的,可以销毁它。
结构体dentry_operation指明了VFS操作目录的所有方法,如下:
struct
dentry_operations {
int
(*d_revalidate) (
struct
dentry *,
int
);
int
(*d_hash) (
struct
dentry *,
struct
qstr *);
int
(*d_compare) (
struct
dentry *,
struct
qstr *,
struct
qstr *);
int
(*d_delete) (
struct
dentry *);
void
(*d_release) (
struct
dentry *);
void
(*d_iput) (
struct
dentry *,
struct
inode *);
};
其实,如果VFS遍历路径名中所有的元素并将它们逐个地解析成目录项对象,将是一件非常耗时的事情。所以内核将目录项对象缓存在目录项缓存(dcache)中,目录项缓存包括三个主要部分:
1.“被使用的”目录项链表,该链表通过索引节点对象中的i_dentry项连接相关的索引节点,因为一个给定的索引节点可能有多个链接,所以就可能有多个目录项对象,因此用一个链表来连接它们。
2.“最近被使用的”双向链表。该链表包含未被使用的和负状态的目录项对象。该链表是按时间插入的。
3. 哈希表和相应的哈希函数用来快速地将给定路径解析为相关目录项对象。
哈希表有数组dentry_hashtable表示,其中每一个元素都是一个指向具有相同键值的目录项对象链表的指针。数组的大小取决于系统中物理内存的大小。实际的哈希值由d_hash()计算,它是内核提供给文件系统的唯一的一个哈希函数。查找哈希表要通过d_lookup()函数,如果该函数在dcache中发现了与其相匹配的目录项对像,则匹配对象被返回;否则,返回NULL指针。dcache在一定意义上也提供了对索引节点的缓存。和目录项对象相关的索引节点对象不会被释放,因为目录项会让相关索引节点的使用计数为正,这样就可以确保索引节点留在内存中。只要目录项被缓存,其相应的索引节点也就被缓存了。
4.文件对象:文件对象表示进程以打开的文件。文件对象仅仅在进程观点上代表已打开文件,它反过来指向目录项对象(反过来指向索引节点),其实只有目录项对象才表示已打开的实际文件。虽然一个文件对应的文件对象不是唯一的,但对应的索引节点和目录项对象无疑是唯一的。文件对象由file结构表示,定义在文件linux/fs.h中,如下:
struct
file {
struct
list_head f_list;
/* list of file objects */
struct
dentry *f_dentry;
/* associated dentry object */
struct
vfsmount *f_vfsmnt;
/* associated mounted fs */
struct
file_operations *f_op;
/* file operations table */
atomic_t f_count;
/* file object's usage count */
unsigned
int
f_flags;
/* flags specified on open */
mode_t f_mode;
/* file access mode */
loff_t f_pos;
/* file offset (file pointer) */
struct
fown_struct f_owner;
/* owner data for signals */
unsigned
int
f_uid;
/* user's UID */
unsigned
int
f_gid;
/* user's GID */
int
f_error;
/* error code */
struct
file_ra_state f_ra;
/* read-ahead state */
unsigned
long
f_version;
/* version number */
void
*f_security;
/* security module */
void
*private_data;
/* tty driver hook */
struct
list_head f_ep_links;
/* list of eventpoll links */
spinlock_t f_ep_lock;
/* eventpoll lock */
struct
address_space *f_mapping;
/* page cache mapping */
};
文件对象的操作有file_operations结构表示,在linux/fs.h中,如下:
struct
file_operations {
struct
module *owner;
loff_t (*llseek) (
struct
file *, loff_t,
int
);
ssize_t (*read) (
struct
file *,
char
*,
size_t
, loff_t *);
ssize_t (*aio_read) (
struct
kiocb *,
char
*,
size_t
, loff_t);
ssize_t (*write) (
struct
file *,
const
char
*,
size_t
, loff_t *);
ssize_t (*aio_write) (
struct
kiocb *,
const
char
*,
size_t
, loff_t);
int
(*readdir) (
struct
file *,
void
*, filldir_t);
unsigned
int
(*poll) (
struct
file *,
struct
poll_table_struct *);
int
(*ioctl) (
struct
inode *,
struct
file *, unsigned
int
, unsigned
long
);
int
(*mmap) (
struct
file *,
struct
vm_area_struct *);
int
(*open) (
struct
inode *,
struct
file *);
int
(*flush) (
struct
file *);
int
(*release) (
struct
inode *,
struct
file *);
int
(*fsync) (
struct
file *,
struct
dentry *,
int
);
int
(*aio_fsync) (
struct
kiocb *,
int
);
int
(*fasync) (
int
,
struct
file *,
int
);
int
(*lock) (
struct
file *,
int
,
struct
file_lock *);
ssize_t (*readv) (
struct
file *,
const
struct
iovec *,
unsigned
long
, loff_t *);
ssize_t (*writev) (
struct
file *,
const
struct
iovec *,
unsigned
long
, loff_t *);
ssize_t (*sendfile) (
struct
file *, loff_t *,
size_t
,
read_actor_t,
void
*);
ssize_t (*sendpage) (
struct
file *,
struct
page *,
int
,
size_t
, loff_t *,
int
);
unsigned
long
(*get_unmapped_area) (
struct
file *, unsigned
long
,
unsigned
long
, unsigned
long
,
unsigned
long
);
int
(*check_flags) (
int
flags);
int
(*dir_notify) (
struct
file *filp, unsigned
long
arg);
int
(*flock) (
struct
file *filp,
int
cmd,
struct
file_lock *fl);
};
最后,除了以上几种VFS基础对象外,内核还使用了另外一些数据结构来管理文件系统的其它相关数据,如下:
1.file_system_type:因为linux支持众多的文件系统,所以内核必有由一个特殊的结构来描述每种文件系统的功能和行为:
struct
file_system_type {
const
char
*name;
/* filesystem's name */
struct
subsystem subsys;
/* sysfs subsystem object */
int
fs_flags;
/* filesystem type flags */
/* the following is used to read the superblock off the disk */
struct
super_block *(*get_sb) (
struct
file_system_type *,
int
,
char
*,
void
*);
/* the following is used to terminate access to the superblock */
void
(*kill_sb) (
struct
super_block *);
struct
module *owner;
/* module owning the filesystem */
struct
file_system_type *next;
/* next file_system_type in list */
struct
list_head fs_supers;
/* list of superblock objects */
};
其中,get_sb()函数从磁盘上读取超级块,并且在文件系统被安装时,在内存中组装超级块对象,剩余的函数描述文件系统的属性。每种文件系统,不管有多少个实力安装到系统中,还是根本就没有安装到系统中,都只有一个file_system_type结构。更有趣的是,当文件系统被实际安装时,将有一个vfsmount结构体在安装点被创建。该结构体被用来代表文件系统的实例----换句话说,代表一个安装点.
2.vfsmount结构被定义在linux/mount.h中,下面是具体结构:
struct
vfsmount {
struct
list_head mnt_hash;
/* hash table list */
struct
vfsmount *mnt_parent;
/* parent filesystem */
struct
dentry *mnt_mountpoint;
/* dentry of this mount point */
struct
dentry *mnt_root;
/* dentry of root of this fs */
struct
super_block *mnt_sb;
/* superblock of this filesystem */
struct
list_head mnt_mounts;
/* list of children */
struct
list_head mnt_child;
/* list of children */
atomic_t mnt_count;
/* usage count */
int
mnt_flags;
/* mount flags */
char
*mnt_devname;
/* device file name */
struct
list_head mnt_list;
/* list of descriptors */
struct
list_head mnt_fslink;
/* fs-specific expiry list */
struct
namespace
*mnt_namespace
/* associated namespace */
};
vfs中维护的各种链表是为了跟踪文件系统和所有其他安装点的关系,mnt_flags保存了安装时指定的标志信息,下表给出了标准的安装标志:
安装那些管理不充分信任的移动设备时,这些标志很有用处。
系统中每一个进程都有自己的一组打开的文件,有三个数据结构将VFS层和文件的进程紧密联系在一起,它们分别是file_struct,fs_struct和namespace.
1.file_struct:该结构体有进程描述符中的files域指向,如下:
struct
files_struct {
atomic_t count;
/* structure's usage count */
spinlock_t file_lock;
/* lock protecting this structure */
int
max_fds;
/* maximum number of file objects */
int
max_fdset;
/* maximum number of file descriptors */
int
next_fd;
/* next file descriptor number */
struct
file **fd;
/* array of all file objects */
fd_set *close_on_exec;
/* file descriptors to close on exec() */
fd_set *open_fds;
/* pointer to open file descriptors */
fd_set close_on_exec_init;
/* initial files to close on exec() */
fd_set open_fds_init;
/* initial set of file descriptors */
struct
file *fd_array[NR_OPEN_DEFAULT];
/* default array of file objects */
};
2.第二个结构体是fs_struct:由进程描述符的fs域指向。它包含文件系统和进程相关的信息,在linux/fs_struct.h中,如下:
struct
fs_struct {
atomic_t count;
/* structure usage count */
rwlock_t lock;
/* lock protecting structure */
int
umask;
/* default file permissions*/
struct
dentry *root;
/* dentry of the root directory */
struct
dentry *pwd;
/* dentry of the current directory */
struct
dentry *altroot;
/* dentry of the alternative root */
struct
vfsmount *rootmnt;
/* mount object of the root directory */
struct
vfsmount *pwdmnt;
/* mount object of the current directory */
struct
vfsmount *altrootmnt;
/* mount object of the alternative root */
};
3.最后一个是namespace:由进程描述符namespace域指向,定义在linux/namespace.h中,如下:
struct
namespace
{
atomic_t count;
/* structure usage count */
struct
vfsmount *root;
/* mount object of root directory */
struct
list_head list;
/* list of mount points */
struct
rw_semaphore sem;
/* semaphore protecting the namespace */
};
- linux内核分析笔记----虚拟文件系统(下)
- linux内核分析笔记----虚拟文件系统(下)
- linux内核分析笔记----虚拟文件系统(上)
- linux内核分析笔记----虚拟文件系统(上)
- linux 虚拟文件系统分析笔记
- Linux内核源代码情景分析-虚拟文件系统
- linux下虚拟文件系统
- Linux内核学习笔记十——虚拟文件系统概念
- Linux内核设计与实现 学习笔记(3)虚拟文件系统
- Linux内核学习笔记十——虚拟文件系统概念
- Linux内核学习笔记十——虚拟文件系统概念
- linux虚拟内核文件系统介绍
- Linux内核-文件系统之虚拟文件系统
- Linux虚拟文件系统源码分析
- linux虚拟文件系统(VFS)笔记
- Linux内核具体体系结构之虚拟文件系统
- Linux内核具体体系结构之虚拟文件系统
- Linux虚拟文件系统(内核初始化<一>)
- UVa 10499 The Land of Justice(简单数学)
- 看懂信息检索和网络数据挖掘领域论文的必备知识总结
- Kinect应用开发汇总
- mysql++ 中遇到的安装问题 及linux下C++添加共享库
- hdu 1176 免费馅饼 (数塔)
- linux内核分析笔记----虚拟文件系统(下)
- 算法入门经典-1
- POJ-2191-Mersenne Composite Numbers
- sky数
- ubuntu12.04samba服务器配置
- 话题模型(topic model)的提出及发展历史
- android4.2 锁屏源码分析
- MVC
- Context类详解