现在的位置: 首页 > 综合 > 正文

Linux kernel 绝对路径之自己实现篇

2013年10月11日 ⁄ 综合 ⁄ 共 1750字 ⁄ 字号 评论关闭

一. 情景模式

1.  获取文件的绝对路径,这里指由fd获取
2.  获取进程的绝对路径

二. linux kernel 和路径有关的2个数据结构:

1. struct dentry 文件名保存在这个结构体

结构体原型:
struct dentry {
	int d_mounted;
	struct inode *d_inode;/* Where the name belongs to - NULL is negative */
	struct hlist_node d_hash;	/* lookup hash list */
	struct dentry *d_parent;	/* parent directory */
	struct qstr d_name;         /* 文件名在这里 */
    /* 省略若干内容 */
};

2. struct vfsmount 文件系统的挂载信息,mount 命令

结构体原型:
struct vfsmount {
	struct list_head mnt_hash;
	struct vfsmount *mnt_parent;	/* fs we are mounted on */
	struct dentry *mnt_mountpoint;	/* dentry of mountpoint */
	struct dentry *mnt_root;	    /* root of the mounted tree */

    /* 省略若干内容 */
};

三. 从struct dentry 和struct vfsmount 回溯直到/ ,即可拼凑出完整路径

获取进程绝对路径例子一个:
void get_absolute_path()
{
    /* 假设 512 已经足够了 */
    char * tmp_path[512];
    char * ptr        = NULL;
    struct dentry *dentry = NULL;
    struct vfsmount * mnt = NULL;

    memset(tmp_path,'\0',512);
    ptr = tmp_path + 512 -1;

    task_lock(current);
    /* Get the Process working dentry */
    dentry = current->fs->pwd.dentry;

    /* Get the Process working vfsmount */
    mnt = current->fs->pwd.mnt;
    do
    {
        /* Process the dentry */
        while(dentry && dentry->d_name.name && strcmp(dentry->d_name.name,"/"))
        {
                ptr = ptr - strlen(dentry->d_name.name);
                if(ptr <= tmp_path + strlen(dentry->d_name.name) + 1)
                {
                    break;
                }
                memcpy(ptr,dentry->d_name.name,strlen(dentry->d_name.name));
                *(--ptr) = '/';
                dentry= dentry->d_parent;
        }
        /* Process the filesystem mountpoint, 突破挂载点 */
        if(mnt && mnt->mnt_mountpoint\
               && mnt->mnt_mountpoint->d_name.name\
               && strcmp(mnt->mnt_mountpoint->d_name.name,"/"))
        {
                dentry = mnt->mnt_mountpoint;
                ptr = ptr - strlen(dentry->d_name.name);
                if(ptr <= tmp_path + strlen(dentry->d_name.name) + 1)
                {
                    break;
                }
                memcpy(ptr,dentry->d_name.name,strlen(dentry->d_name.name));
                *(--ptr) = '/';
                mnt = mnt->mnt_parent;
                dentry= dentry->d_parent;
        }
    }while( 0 !=  strcmp(mnt->mnt_mountpoint->d_name.name,"/")); /* end do */
    /* 直到文件系统的挂载点为 / */

    task_unlock(current);
    printk("full path: %s\n",ptr);
}

由于自己实现,考虑不周,当遇到目录挂载目录(mount --rbind)时,处理可能会出问题。

更好的方法且见下回分解

抱歉!评论已关闭.