当前位置:编程学习 > C/C++ >>

操作系统大型实验进展(6)-----Linux 内核文件系统与设备操作流程分析

 
本笔记对 linux kernel 的文件系统操作以及设备操作进行了分析,主要是针
对 ext3 文件系统的 open 流程的分析,目的是为了解答心中的几个疑问:
 
1、一个文件的操作流程,系统是如何把 struct file 与 struct dentry
   以及 struct inode 结合起来的?
 
2、文件与设备驱动都是对 VFS(Virtual File System) 抽象出来的 struct file 
   进行操作的,那么系统是如何区分的?在哪里开始区分的?
 
3、linux 内核中没有类 UNIX VFS(Virtual File System) 提供的 struct vnode
   结构,那么具体的文件操作是如何与实际文件系统的操作挂钩的?
 
4、超级块(super block)在文件与设备驱动操作中起到的作用?
 
5、在以前的尝试中对 struct file 做手脚为什么影响不到全局?
 
6、在文件系统内核有几个函数操作集?有何不同?分别是在什么时候赋值?
 
注:此文档是根据当时的分析过程记录的,分析顺序也就没有再更改过,
    每个人读内核源码的思路不同,或者说目的不同,流程自然也就不同。
    所以在别人看来我所记录的可能比较凌乱。如果真是这样,那我只能
    说句抱歉,因为我并不打算再修改记录顺序。最后还是那句话,如果
    您在阅读本文时发现了错误,还望得到您的指正。
 
 
我们知道在 linux kernel 中,如果想操作一个文件,首先要通过 filp_open()
这个 kernel api 来打开这个文件,那么我们就从这里入手分析。可以看到
filp_open() 函数只是个简单封状,具体实现是 do_filp_open() 函数,函数
本身先通过 open_namei() 函数得到一个 fd 对应的 struct nameidata 结构。
最后使用 nameidata_to_filp() 函数返回一个 struct file 结构。
 
static struct file *do_filp_open(int dfd, const char *filename, int flags,
int mode)
{
int namei_flags, error;
struct nameidata nd;
 
namei_flags = flags;
if ((namei_flags+1) & O_ACCMODE)
namei_flags++;
 
        //
        // 这个函数调用 path_lookup_xxx() 等函数根据路径名称
        // 返回一个 struct nameidata 结构。这个函数完成了很多
        // 工作,后面会随着疑问详细分析这个函数。这里只需要知
        // 道它返回了一个 nameidata 结构。
        //
error = open_namei(dfd, filename, namei_flags, mode, &nd);
if (!error)
                
                //
                // 这里返回的 struct file 结构已经创建并填充完毕了。
                // 直接返回给调用者。
                //
return nameidata_to_filp(&nd, flags);
 
return ERR_PTR(error);
}
 
 
这个函数根据 struct nameidata 结构返回一个 struct file。可以看到
struct file 是在使用了 __dentry_open() 函数后被填充的,且使用的第
一个参数是 nameidata->dentry,这也是为什么我们要获得 struct nameidata
的一个主要原因,其目的就是为了得到 struct dentry 结构。
 
struct file *nameidata_to_filp(struct nameidata *nd, int flags)
{
struct file *filp;
 
/* Pick up the filp from the open intent */
filp = nd->intent.open.file;
/* Has the filesystem initialised the file for us? */
if (filp->f_dentry == NULL)
 
                //
                // 这个函数主要就是填充一个 struct file 结构,通过这段
                // 代码也可以看到,一个 struct file 是动态分配的。
                //
filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
else
path_release(nd);
return filp;
}
 
 
此函数分配并填充一个 struct file 结构。从这个函数中很明显可以看到,
一个 struct file 结构是使用 struct dentry,struct inode,struct vfsmount
结构中的相关信息填充的。在 struct dentry 中有一个区域指向了 struct inode 
结构,这也就是为什么我们要获得 struct dentry 原因之一。有了 struct inode
结构我们就可以得到一个文件的相关信息和实际文件系统所提供的函数,如 ext3 
文件系统。或者是一个设备驱动所提供的方法,如字符设备驱动。为什么这么说?
看下面的详细记录。
 
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
int flags, struct file *f,
int (*open)(struct inode *, struct file *))
{
struct inode *inode;
int error;
 
        //
        // 得到访问标志
        // 
f->f_flags = flags;
f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
FMODE_PREAD | FMODE_PWRITE;
        //
        // 通过 struct dentry 得到 struct inode 结构
        //
inode = dentry->d_inode;
 
        //
        // 判断这个文件(inode) 是否有写权限,没有则
        // 跳转到 cleanup_file 处退出
        //
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
if (error)
goto cleanup_file;
}
 
        //
        // 使用 vfsmount,dentry,inode 结构
        // 填充 struct file 中相关域。
        //
f->f_mapping = inode->i_mapping;
f->f_dentry = dentry;
f->f_vfsmnt = mnt;
f->f_pos = 0;
 
        //
        // 注意:这里使用的是 struct inode 中的 struct file_operations
        // 回调函数来填充的 struct file->f_op。也就是说 struct file 中的
        // 函数其实是 inode->file_operations 的一份复制品。而这个 struct
        // file 很明显是动态创建的,也就是说 open 一个文件则会动态生成一个
        // struct file 结构,并把 inode->i_fop 函数给它,struct file 并不是
        // 全局唯一的,而是与进程相关的,在 task_struct 中的 files_struct 
        // 结构则是 struct file 的一个集合。这也就是为什么在 struct file
        // 里做了手脚,影响的仅是当前进程,而不是全局的原因。;)
        //
f->f_op = fops_get(inode->i_fop);       
file_move(f, &inode->i_sb->s_files);
 
        //
        // 注意:这里调用了 struct file->f_op->open 函数,也就是说调用了
        // struct inode->i_fop->open 函数。这里有必要注
补充:软件开发 , C语言 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,