加入收藏 | 设为首页 | 会员中心 | 我要投稿 徐州站长网 (https://www.0516zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux中文件名解析处理源码分析

发布时间:2016-09-21 00:04:02 所属栏目:Linux 来源:站长网
导读:前言 Linux中对一个文件进行操作的时候,一件很重要的事情是对文件名进行解析处理,并且找到对应文件的inode对象,然后创建表示文件的file对象。在此,对文件名

前言

Linux中对一个文件进行操作的时候,一件很重要的事情是对文件名进行解析处理,并且找到对应文件的inode对象,然后创建表示文件的file对象。在此,对文件名解析过程,并且如何找到对应inode的过程进行源码分析。分析代码基于Linux-3.2版本。

关键函数分析

不管是通过应用层的API函数还是在内核中打开一个文件,最终都需要调用filp_open函数,该函数的主要职责就是解析文件名,找到文件对应的inode对象,然后分配内存创建file对象,最后执行该文件对应的file->open函数。

filp_open的核心处理函数是path_openat,该函数分析如下:

static struct file *path_openat(int dfd, const char *pathname,  
        struct nameidata *nd, const struct open_flags *op, int flags)  
{  
    struct file *base = NULL;  
    struct file *filp;  
    struct path path;  
    int error;  
    /* 创建一个file对象 */
    filp = get_empty_filp();  
    if (!filp)  
        return ERR_PTR(-ENFILE);  
     
    filp->f_flags = op->open_flag;  
    nd->intent.open.file = filp;  
    nd->intent.open.flags = open_to_namei_flags(op->open_flag);  
    nd->intent.open.create_mode = op->mode;  
    /* 初始化检索的起始目录,判断起始目录是根目录还是当前目录,并且初始化nd->inode对象,为link_path_walk函数的解析处理做准备。 */
    error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);  
    if (unlikely(error))  
        goto out_filp;  
     
    current->total_link_count = 0;  
    /* 关键的字符串解析处理函数,其核心思想是分级解析字符串,通过字符串对应的目录项找到下一级目录的inode节点。该函数的具体分析如下。 */
    error = link_path_walk(pathname, nd);  
    if (unlikely(error))  
        goto out_filp;  
    /* do_last函数创建或者获取文件对应的inode对象,并且初始化file对象,至此一个表示打开文件的内存对象filp诞生 */
    filp = do_last(nd, &path, op, pathname);  
    while (unlikely(!filp)) { /* trailing symlink */
        struct path link = path;  
        void *cookie;  
        if (!(nd->flags & LOOKUP_FOLLOW)) {  
            path_put_conditional(&path, nd);  
            path_put(&nd->path);  
            filp = ERR_PTR(-ELOOP);  
            break;  
        }  
        nd->flags |= LOOKUP_PARENT;  
        nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);  
        error = follow_link(&link, nd, &cookie);  
        if (unlikely(error))  
            filp = ERR_PTR(error);  
        else
            filp = do_last(nd, &path, op, pathname);  
        put_link(nd, &link, cookie);  
    }  
out:  
    if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))  
        path_put(&nd->root);  
    if (base)  
        fput(base);  
    release_open_intent(nd);  
    return filp;  
     
out_filp:  
    filp = ERR_PTR(error);  
    goto out;  
}

(编辑:徐州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读