一. 情景模式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)時,處理可能會出問題。更好的方法且見下回分解