今天我们看一些在linux系统里边经常使用的cd命令对应的内核实现,就是sys_chdir函数的实现。
sys_chdir函数在fs/open.c里,定义如下
然后我们看set_fs_pwd函数,这个函数定义在fs/namespace.c里,定义如下
从这里我们就可以看书vfs_lookup是内核里贯穿文件系统的一个函数,理解了vfs_lookup函数,就基本上可以说是对于文件系统有了一个大致的了解了。
sys_chdir函数在fs/open.c里,定义如下
asmlinkage long sys_chdir(const char __user * filename)
{
/*路径名查找函数*/
struct nameidata nd;
int error;
/*之前我们分析过,根据得到的文件名,找到对应的dentry和mnt结构体放入nameidata结构体里边*/
error = __user_walk(filename,
LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
if (error)
goto out;
/*vfs层权限检查,前边也分析过*/
error = vfs_permission(&nd, MAY_EXEC);
if (error)
goto dput_and_out;
/*主要的工作函数,设置进程当前工作路径*/
set_fs_pwd(current->fs, nd.mnt, nd.dentry);
dput_and_out:
/*释放建立的nameidata结构体*/
path_release(&nd);
out:
return error;
}
然后我们看set_fs_pwd函数,这个函数定义在fs/namespace.c里,定义如下
void set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
struct dentry *dentry)
{
/*指向当前进程结构体里的fs_struct里的dentry和mnt结构体,就是原来的路径*/
struct dentry *old_pwd;
struct vfsmount *old_pwdmnt;
write_lock(&fs->lock);
old_pwd = fs->pwd;
old_pwdmnt = fs->pwdmnt;
/*把进程结构体task_struct里的pwd和pwdmnt指向新的dentry和vfsmount结构体*/
fs->pwdmnt = mntget(mnt);
fs->pwd = dget(dentry);
write_unlock(&fs->lock);
/*释放原先的dentry和vfsmount*/
if (old_pwd) {
dput(old_pwd);
mntput(old_pwdmnt);
}
}
从这里我们就可以看书vfs_lookup是内核里贯穿文件系统的一个函数,理解了vfs_lookup函数,就基本上可以说是对于文件系统有了一个大致的了解了。