1、进程调用库函数向内核发起读文件请求,主要是文件的open过程
输入为文件路径名,输出为文件描述符 [fd在特定于进程的数组中充当位置索引(数组是task_struct->files->fd_array)],中间是如果进行转化的?
- 首先引入一个nameidata的结构暂存临时结果
- 根据根目录的dentry实例化一个nameidata
- 对目录进行操作
* dentry->d_mounted中可判断一个目录是一个已装载文件系统的根目录
* 是则定位装载点vfsmount->mnt_mountpoint = dentry
* 普通文件则查找dentry->d_inode是否在缓存中,不在的话需在底层文件系统(ext2)发起一个查找操作
* 具体为vfs层调用real_lookup,根据dentry->d_parent->d_inode->i_op->lookup调用到ext2_lookup函数
* 读目录项到内存中,直到执行到最后一个文件,此时inode的i_op域的初始化为ext2_file_inode_operations
struct task_struct {
...
struct fs_struct *fs;
struct files_struct *files;
...
};
struct fs_struct {
...
struct dentry * root, * pwd, * altroot;
struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
};
struct nameidata {
struct dentry *dentry;
struct vfsmount *mnt;
struct qstr last;
unsigned int flags;
int last_type;
};
struct dentry {
....
struct inode *d_inode;
....
struct dentry *d_parent;
...
struct list_head d_subdirs;
...
struct dentry_operations *d_op;
struct super_block *d_sb;
...
int d_mounted;/*对于安装点而言表示是否被挂载文件系统,是不是一个挂载点*/
...
};
struct inode {
...
const struct inode_operations *i_op; /* 索引节点操作函数 */
const struct file_operations *i_fop; /* 缺省的索引节点操作 */
...
};
const struct inode_operations ext2_dir_inode_operations = {
.create = ext2_create,
.lookup = ext2_lookup,
...
};
struct files_struct {
...
struct file * fd_array[NR_OPEN_DEFAULT];
};
struct file{
...
struct file_operations *f_op;
...
};
struct file_operations
{
ssize_t (*read)(struct file *,char *, size_t, loff_t *);
...
};
2、内核通过检查进程的文件描述符定位到虚拟文件系统的已打开文件列表表项;
3、调用系统调用函数read(),进而调用file实例的read()函数