一、进程与vfs对象之间的关系很重要
1、文件对象用于描述进程怎样与一个打开的文件进行交互。
2、文件对象是在文件被打开的时候,由进程创建的,由一个file结构来描述,文件结构也仅仅存在于内存中。3、文件对象中存了一个重要信息:文件指针(文件当前位置),几个进程可能同时访问同一文件,因此文件指针必须
存放在文件对象,而非索引节点。 这也是为什么一个文件被打开一次,就要创建一次文件对象。
二、文件对象file结构及文件操作函数
struct file {
struct pathf_path; // 与文件关联的目录项对象指针
//含有该文件的已安装文件系统
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
const struct file_operations*f_op; //文件操作函数指针
atomic_long_t f_count; //文件对象初引用次数
fmode_t f_flags; //打开文件标志
loff_t f_pos; 当前文件位置(文件指针)
/* needed for tty driver, and maybe others */
void*private_data; // 特定文件系统私有数据
struct address_space*f_mapping; /后面研究
};
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int); //文件定位
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); //读
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); //写
unsigned int (*poll) (struct file *, struct poll_table_struct *); //检查文件上的操作
int (*mmap) (struct file *, struct vm_area_struct *); //内存映射
int (*open) (struct inode *, struct file *); //打开或创建文件对象
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync); //文件缓存写入磁盘
。。。。。。
};
三、文件对象创建
下面以sdcardfs的open操作方法说明文件对象创建过程:
static int sdcardfs_open(struct inode *inode, struct file *file, bool isdir)
{
struct file *lower_file = NULL;
。。。。。。
lower_file =dentry_open(lower_path.dentry, lower_path.mnt,
file->f_flags, current_cred());
。。。。。。
}
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
const struct cred *cred)
{
struct file *f;
f = get_empty_filp(); //从slab高速缓存中申请file对象内存
。。。。。。
f->f_flags = flags; //初始化flag
return __dentry_open(dentry, mnt, f, NULL, cred); //调用__dentry_open初始化file
}
继续跟踪__dentry_open()函数:
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
static const struct file_operations empty_fops = {};
struct inode *inode;
int error;
f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | //文件模式
FMODE_PREAD | FMODE_PWRITE;
if (unlikely(f->f_flags & O_PATH))
f->f_mode = FMODE_PATH;
inode = dentry->d_inode; //获取该文件的索引节点inode
if (f->f_mode & FMODE_WRITE) {
error = __get_file_write_access(inode, mnt);
if (error)
goto cleanup_file;
if (!special_file(inode->i_mode))
file_take_write(f);
}
f->f_mapping = inode->i_mapping; //mapping以后专门研究
f->f_path.dentry = dentry; //初始化f_path指向的dentry
f->f_path.mnt = mnt; //初始化f_path指向的mnt
f->f_pos = 0; //初始化文件指针
file_sb_list_add(f, inode->i_sb);
if (unlikely(f->f_mode & FMODE_PATH)) {
f->f_op = &empty_fops;
return f;
}
f->f_op = fops_get(inode->i_fop); //从inode中获取文件的操作方法
if (!open && f->f_op)
open = f->f_op->open; //执行特定文件系统的文件对象open操作函数
if (open) {
error = open(inode, f);
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
i_readcount_inc(inode);
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
/* NB: we're sure to have correct a_ops only after f_op->open */
if (f->f_flags & O_DIRECT) { //mapping 以后专门研究
if (!f->f_mapping->a_ops ||
((!f->f_mapping->a_ops->direct_IO) &&
(!f->f_mapping->a_ops->get_xip_mem))) {
fput(f);
f = ERR_PTR(-EINVAL);
}
}
return f;
。。。。。。。。。。。。。。
}
这样文件对象的创建程就很清楚了,更详细的文件系统的open过程,以后再研究。