linux内核模块中fd inode的可执行路径

Posted

技术标签:

【中文标题】linux内核模块中fd inode的可执行路径【英文标题】:Executable path from fd inode in a linux kernel module 【发布时间】:2013-04-25 10:30:15 【问题描述】: 给定一个存在于/proc/**/fd/* 中的inode 还有一个需要从符号链接/proc/**/exe中找到可执行路径的Linux内核模块

我怎样才能实现这一点,以便从一个 inode 号我使用 fd 获得可执行文件的路径?

【问题讨论】:

在我的研究中,我发现了一个方法 proc_fd_link (lxr.free-electrons.com/source/fs/proc/fd.c?a=avr32#L140),但无法从我的内核模块访问(编译时找不到该方法。 我还找到了宏 PDEPROC_I (lxr.free-electrons.com/source/include/linux/proc_fs.h) 但后来我不知道如何找到 /proc/**/exe 项。 一个inode可能没有或有多个路径,命名空间可能导致不同进程中的不同路径。你需要什么路径,为什么必须从内核模块完成? @CL。在内核模块中执行它不是强制性的(我目前正在用户空间应用程序中实现它)。你说的“你需要什么路径”是什么意思? 所以你要重新实现lsof? 【参考方案1】:

proc_inode struct 和 PROC_I macro 都是内部的。见[PATCH 27/28] proc: Make the PROC_I() and PDE() macros internal toprocfs [RFC]。

相反,迭代 inode 的 dentry 列表怎么样?您可以使用dentry_path_raw() 来查找/*/fd/* 路径名:

//struct inode *proc_inode;

struct dentry *dentry;
pid_t pid;
int found_match = 0;

printk(KERN_DEBUG "superblock type name: %s\n", proc_inode->i_sb->s_type->name);

// An inode's dentry list is protected by the i_lock. See:
// - "dcache->d_inode->i_lock protects: i_dentry, d_u.d_alias, d_inode of aliases"
//   http://lxr.free-electrons.com/source/fs/dcache.c?v=4.0#L48
// - The implementation of d_prune_aliases()
//   http://lxr.free-electrons.com/source/fs/dcache.c?v=4.0#L882
spin_lock(&proc_inode->i_lock);
hlist_for_each_entry(dentry, &proc_inode->i_dentry, d_u.d_alias) 
    char buf[64];
    const char *path_raw;
    char c;

    path_raw = dentry_path_raw(dentry, buf, sizeof(buf));

    // dentry_path_raw() places the path into `buf'. If `buf' is not large
    // enough, then continue on to the next dentry.
    if (!(buf <= path_raw && path_raw <= buf + sizeof(buf) - 1)) 
        printk(KERN_DEBUG "`buf' not large enough, dentry_path_raw() returned %ld\n", PTR_ERR(path_raw));
        continue;
    

    printk(KERN_DEBUG "path_raw = %s\n", path_raw);

    // We're looking to match: ^/(\d*)/fd/

    if (*path_raw++ != '/') continue;

    pid = 0;
    for (c = *path_raw; c; c = *++path_raw) 
        if ('0' <= c && c <= '9') 
            pid = 10 * pid + (c - '0');
         else 
            break;
        
    

    if (*path_raw++ != '/') continue;
    if (*path_raw++ != 'f') continue;
    if (*path_raw++ != 'd') continue;
    if (*path_raw != '/' && *path_raw != '\0') continue;

    // Found a match. Break the dentry list loop.
    found_match = 1;
    printk(KERN_DEBUG "breaking dentry list loop\n");
    break;

spin_unlock(&proc_inode->i_lock);

if (found_match) 
    printk(KERN_DEBUG "pid = %d\n", (int)pid);

编辑:我已将一个演示项目上传到 GitHub:https://github.com/dtrebbien/so16317923-proc-fs-kernel-module

【讨论】:

谢谢!我去看看

以上是关于linux内核模块中fd inode的可执行路径的主要内容,如果未能解决你的问题,请参考以下文章

linux /proc/[pid]/fd 中socket描述符后面的数字是什么意思?inode(information node)

文件IO详解---文件描述符(fd)和inode号的关系

在创建管道,fifo或套接字时创建inode

模块内的相对文件系统写入路径

探秘linux-文件管理(inode理解)及管道和IO重定向

UNIX读写数据过程