歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux虛擬文件系統--文件路徑名的解析(1)--整體過程

Linux虛擬文件系統--文件路徑名的解析(1)--整體過程

日期:2017/2/28 15:28:34   编辑:Linux教程

文件路徑名的解析是VFS中最基本也是最頻繁用到的一個部分,它的代碼實現還是十分繁雜的,主要是因為除了普通文件名的解析,內核還要考慮各種可能出現的情況,如一個目錄下掛載了多個文件系統,路徑中的符號鏈接等等……後面我會分幾次將整個過程進行一個盡量仔細的分析,其中所涉及到的各種數據結構在ULK等相關內核書籍上都有比較詳細的介紹,就不列出來了

相關閱讀:Linux虛擬文件系統--文件路徑名的解析(2)--回退父目錄 http://www.linuxidc.com/Linux/2012-11/74575.htm

文件路徑名的解析路口函數為path_lookup(),如下:

int path_lookup(const char *name, unsigned int flags,
struct nameidata *nd)
{
return do_path_lookup(AT_FDCWD, name, flags, nd);
}

name:路徑名

flags:查找操作的標識

struct nameidata:用於保存當前的相關查找結果

這裡可以看到path_lookup()只是對do_path_lookup()的一層封裝

static int do_path_lookup(int dfd, const char *name,
unsigned int flags, struct nameidata *nd)
{
/*path_init進行一些搜索前的初始化工作,主要是確定起始搜索的起點並保存在nd中*/
int retval = path_init(dfd, name, flags, nd);

if (!retval)//初始化沒問題的話就開始解析
retval = path_walk(name, nd);
if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
nd->path.dentry->d_inode))
audit_inode(name, nd->path.dentry);
if (nd->root.mnt) {
path_put(&nd->root);
nd->root.mnt = NULL;
}
return retval;
}


static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
{
int retval = 0;
int fput_needed;
struct file *file;
nd->last_type = LAST_ROOT; /* if there are only slashes... */
nd->flags = flags;
nd->depth = 0;
nd->root.mnt = NULL;
if (*name=='/') {//如果文件路徑是以絕對路徑的形式給出
set_root(nd);//設置nd的根目錄
nd->path = nd->root;//當前的path從根目錄開始
path_get(&nd->root);
} else if (dfd == AT_FDCWD) {
struct fs_struct *fs = current->fs;
read_lock(&fs->lock);
nd->path = fs->pwd;//獲取當前目錄的path
path_get(&fs->pwd);
read_unlock(&fs->lock);
} else {
struct dentry *dentry;
/*根據dfd,從當前進程的fs_struct結構的fdtable中取出文件描述符指針*/
file = fget_light(dfd, &fput_needed);
retval = -EBADF;
if (!file)
goto out_fail;
//從文件描述符中獲取dentry
dentry = file->f_path.dentry;
retval = -ENOTDIR;
if (!S_ISDIR(dentry->d_inode->i_mode))//如果不是目錄
goto fput_fail;
//相應的權限檢查
retval = file_permission(file, MAY_EXEC);
if (retval)
goto fput_fail;
nd->path = file->f_path;//獲取path
path_get(&file->f_path);
fput_light(file, fput_needed);
}
return 0;
fput_fail:
fput_light(file, fput_needed);
out_fail:
return retval;

Copyright © Linux教程網 All Rights Reserved