学习网考试学习资料

Gzu521.com

Linux学习笔记(8)

LINUX教程   点击:次   发布时间:2006-12-19   【字体: 】   来源:blog
贵 州 学 习 网

目录项的状态

每个目录项属于以下4种状态之一:
空闲状态:目录项不包含有效信息,未被vfs使用,由slab分配器进行管理。
未使用状态:目录项还没有被使用,d_count为null,但是其d_inode仍然指向相关的索引节点。该目录项包含有效信息,但必要时,其内容可以被丢弃。
正在使用状态:目录项正在被使用,d_count>0,d_inode指向相关的索引节点,包含有效信息,不能被丢弃。
负状态:与目录项相关索引节点已不存在,d_inode为null

未用目录项链表
目录项哈希管理
父子目录关系
目录项与索引节点


file对象

在include/linux/fs.h中定义了file结构,用于保存文件位置等对文件的操作信息。描述的是进程怎样与一个打开文件的交互过程
file对象是在文件打开描述符创建。
多个file结构可以指向同一个文件。

file域

struct file { /* 定义在include/linux/fs.h */
struct list_head f_list; /*形成链表*/
struct dentry *f_dentry; /*文件对应的dentry结构*/
struct vfsmount *f_vfsmnt; /*文件所在文件系统的vfsmount结构*/
struct file_operations *f_op; /*文件操作函数结构*/
atomic_t f_count; /*引用计数*/ n unsigned int f_flags; /*文件标识*/
mode_t f_mode; /*文件打开方式*/
loff_t f_pos; /*文件当前位置*/
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; n /*预读标识、预读最多页面数,上次预读后的文件指针、预读字节数、预读页面数*/
struct fown_struct f_owner; /*异步i/o消息的文件拥有者*/
unsigned int f_uid, f_gid; /*赋予当前进程的uid和gid*/
int f_error; /*网络写操作的错误码*/
unsigned long f_version; /*版本号*/
void *private_data; /*文件私有数据区*/

file 对象

每个文件对象总是包含在下列链表之一:

以打开的文件链表:超级块的s_files作为头节点,链入属于该文件系统的已打开的文件
“未使用”文件对象链表:既可以用作文件对象的内存高速缓存,又可以当作超级用户的备用存储器,即使系统动态内存用完,也允许超级用户打开文件。

在这个链表中的对象,f_count总是null,链表首元素地址放在free_list(定义在fs/file_table.c中)。该链表至少包含nr_reserved_files(定义在include/linux/fs.h,默认为10)个对象。 n

新分配文件对象链表:每个元素至少有一个进程使用,f_count!= n null,首元素地址存放在anon_list(定义在fs/file_table.c中)。

当需要分配一个新文件对象时,调用get_empty_filp (定义在fs/ file_table.c中) ,如果未使用链表中的元素个数多于nr_reserved_files,则为新文件使用其中一个元素,否则进入正常内存分配。

文件系统打开的文件链表

与进程相关的文件结构
files_struct
fs_struct

files_struct:进程打开文件表

对于每个进程,包含一个files_struct结构,用来记录文件描述符的使用情况,定义在include/linux/sched.h

files_struct

struct files_struct {
atomic_t count; /*使用该表的进程数*/
rwlock_t file_lock; /*锁*/
int max_fds; /*当前文件对象的最大数*/
int max_fdset; /*当前文件描述符最大数*/
int next_fd; /*数值最小的最近关闭文件的文件描述符*/
struct file ** fd; /*指向文件对象数组的指针*/
fd_set *close_on_exec; /*指向执行exec时需要关闭的文件描述符*/
fd_set *open_fds; /*指向文件描述符屏蔽字集合*/
fd_set close_on_exec_init;/*执行exec时需要关闭的文件描述符初值集合*/
fd_set open_fds_init; /*文件描述符的屏蔽字集合*/
struct file * fd_array[nr_open_default];/*文件对象指针数组*/
}; /*nr_open_default=32*/

fd指向文件对象的指针数组,数组长度存放在max_fds中。通常,fd指向fd_array,fd_array大小为32。如果进程打开的文件数多于32,内核就分配一个新的更大的文件指针数组,其地址放入fd,同时更新max_fds。
open_fds指向open_fds_init,open_fds_init表示当前打开文件的文件描述符屏蔽字。max_fdset存放屏蔽字的位数,默认是1024,需要的时候可以通过expand_fdset( )函数扩展到1024*1024。

可以通过fget( )函数,将文件对象与描述符链接起来

文件系统信息fs_struct

用来描述文件系统信息的fs_struct结构,定义在include/linux/fs_struct.h:
struct fs_struct {
atomic_t count; /*使用该结构的进程数*/
rwlock_t lock; /*读写锁*/
int umask; /*初始文件许可权*/
struct dentry * root, * pwd, * altroot;
/*根目录、当前目录、替换根目录的目录项*/
struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
/*根目录、当前目录、替换根目录的vfsmount结构*/ n};
umask由umask( )系统调用使用,文件打开的实际权限为期望的权限&umask。 n
该结构的一个作用是用于路径定位时,提供根目录、当前目录和替换根目录。

与进程有关的文件结构间的关系


文件系统注册

文件系统是指可能会被挂载到目录树中的各个实际文件系统
注册过程实际上将表示各实际文件系统的 struct file_system_type 数据结构的实例化,然后形成一个链表,内核中用一个名为 file_systems 的全局变量来指向该链表的表头

file_system_type
struct file_system_type {
const char *name; /*文件系统名,出现在/proc/filesystems中,且唯一*/
int fs_flags; /*文件系统标识*/
struct super_block *(*read_super) (struct super_block *, void *, int); /*读取该文件系统在设备上的超级块*/
struct module *owner; /*如果是由模块载入的,则指向该模块;否则,为null*/ n
struct file_system_type * next; /*用于形成注册文件系统链表*/
struct list_head fs_supers; /*超级块链表*/

文件系统的安装
根文件系统的安装

1)建立临时的inode和file对象,在其中填入信息,如设备号,根据文件系统安装标志设置file的f_mode域等
->调用blkdev_open()函数,完成设备的准备工作
->顺序搜索表file_systems中的每一个注册的文件系统,用自己的read_super函数读取root_dev超级块,如果成功,获得根文件系统的超级块和根目录的inode和其目录结构
->把pwd设置为根目录的目录项对象
->调用add_vfsmnt()把第一个元素插入到已安装文件系统链表中

安装常规文件系统
系统安装了根文件系统后,就可以安装其他文件系统。每个文件系统安装在系统目录树的一个目录上。
安装一个文件系统可以通过系统调用mount实现。
mount系统调用在内核的实现函数是sys_mount( ) 。(fs/namespace.c)


整个安装过程中最核心的函数就是do_kern_mount()了,为了创建一个新安装点(vfsmount),该函数需要做一下几件事情:

1 检查安装设备的权利,只有root权限才有能力执行该操作。
2 get_fs_type()在文件链表中取得相应文件系统类型(注册时被填加到练表中)。
3 alloc_vfsmnt()调用slab分配器为vfsmount结构体分配存储空间,并把它的地址存放在mnt局部变量中。
4 初始化mnt->mnt_devname域

5 5 分配新的超级块并初始化它。do_kern_mount( )检查file_system_type描述符中的标志以决定如何进行如下操作:根据文件系统的标志位,选择相应的方法读取超级块(比如对ext2,romfs这类文件系统调用get_sb_dev();对于这种没有实际设备的虚拟文件系统如 ramfs调用get_sb_nodev())——读取超级块最终要使用文件系统类型中的read_super方法


目录项缓存
引言
/home/user/src/foo.c
每次对foo.c访问,vfs都要沿着嵌套目录依次解析全部路径:/、home、user、src和foo.c
为了避免每次访问该路径名都要进行此操作,vfs会在目录项缓存中搜索路径名,如果找到了就无需花费力气解析
相反如果节点该目录项缓存中不存在,vfs就必须解析,完毕后将目录项对象加入到dcache中

上一页 下一页
本文共10页: 第 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

责任编辑:gzu521

电脑课堂分类
Windows 2000教程
Windows XP教程
Windows 2003教程
Windows Vista教程
LINUX教程
软件教学
办公软件
硬件DIY
分类推荐信息
更多...
大类最新文章
更多...