本专栏文章将有70篇左右,欢迎+关注,查看后续文章。
8.4 处理VFS对象
8.4.2 文件操作
本节介绍处理文件的常见操作。
1. 查找inode
根据一个文件名查找 inode。
struct nameidata:
作用:作为查找函数参数。用于传递参数,保存查找结果。
struct nameidata {
struct path path; //记录路径查找结果,path包含dentry和vfsmount。
struct qstr last; //包含了查找文件名,及其hash值。
struct path root; //查找的根路径。
struct inode *inode; //保存找到的inode,等于 path.dentry.d_inode。
unsigned int flags;
unsigned seq;
int last_type; // last的类型(普通文件、目录等)。
unsigned depth; //查找时 跨越的符号链接深度。
char *saved_names[MAX_NESTED_LINKS + 1];
};
struct path {
struct vfsmount *mnt;
struct dentry *dentry;
}
当进程打开一个文件时,将创建一个 nameidata 实例。
通过nameidata中信息,VFS找到对应的文件。
查找函数:
int path_lookupat(int dfd, char *name, unsigned int flags, struct nameidata *nd)
1. path_init:初始化nameidata,返回路径的字符串。
2. link_path_walk:遍历路径中每个节点。
根据文件名查找对应inode,困难点:
1. 存在符号链接。(task_struct->link_count,total_link_count)
2. 须检测装载点。
3. 须检查访问权限。(inode的permission函数)
4. 奇怪的格式,如/./usr/bin/../local,.. 处理较困难。
do_lookup 查找过程:
1. 先在 dentry 缓存中查找 inode,通过 d_revalidate 判断缓存项是否有效。
2. 若缓存无效,则用 real_lookup 调用 inode_operations->lookup 函数。
2. 打开文件
系统调用:sys_open(),调用如下函数:
long do_sys_open(int dfd, char __user *filename, int flags, umode_t mode)
{
int fd = get_unused_fd_flags( flags ); //寻找未使用的文件描述符。
struct file *f = do_filp_open(dfd, tmp, &op, lookup); //查找文件的inode。
fd_install(fd, f); //关联 fd 和 strunct file*。
return fd;
}
3. 读取和写入
sys_read 函数步骤:
1. 读取 file->f_pos 值。
2. vfs_read 调用 file->f_op->read() (默认为 do_sync_read 函数)。
sys_write 同理。