Linux 内核文件系统与设备操作流程分析(6) ((!f->f_mapping->a_ops->direct_IO) && (!f->f_mapping->a_ops->get_xip_page))) { fput(f); f = ERR_PTR(-EINVAL); } } return f;//// 以下两个流程,只有失败时才会走到。释放 struct file 中// 所有相关信息,并返回错误。//cleanup_all: fops_put(f->f_op); if (f->f_mode & FMODE_WRITE) put_write_access(inode); file_kill(f); f->f_dentry = NULL; f->f_vfsmnt = NULL;cleanup_file: put_filp(f); dput(dentry); mntput(mnt); return ERR_PTR(error);}在上面详细分析中介绍的 struct file 中使用的 f_op 其实是 struct inode->i_fop中的一个副本。写过设备驱动的人都知道,在使用 register_xxx 注册一个“字符” 或 “块” 设备驱动时,都要填充一个 struct file 结构以便与应用层交互。那么这样就存在一个问题,大家都知道在 *nix 系统下文件与设备都是以文件形式存在的,即都有 inode,而访问 file system 与 device driver 所使用的函数操作集都是通过 struct inode 提供的,且都是一个 file_operations 函数集,那么系统是如何区分所访问的是 file system 上的文件还是 device driver 呢?如果是device driver 那么又是在什么地方初始化连接你所注册的回调函数呢?下面我们以 ext3 文件系统为例,来看一下 ext3_read_inode() 函数的实现。至于这个函数什么时候被调用,在哪里被调用的?以及下面注释中提到的 ext3 文件系统的 open操作为什么为空操作等疑问会在后面章节中介绍,这里为了结合上下文,保持连贯性,还是先讲一下这个函数。void ext3_read_inode(struct inode * inode){ struct ext3_iloc iloc; struct ext3_inode *raw_inode; struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh;