linux VFS 之四:文件对象file

来源:互联网 发布:网络银行系统架构 编辑:程序博客网 时间:2024/04/30 02:58

一、进程与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过程,以后再研究。







0 0