一. 情景模式
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)时,处理可能会出问题。
更好的方法且见下回分解