如何在Linux内核中找到已打开的inode的所有者进程?

时间:2014-02-18 14:10:55

标签: c linux-kernel

给定一个inode号(一个打开的套接字),我想找到打开套接字的进程,这可能吗?

我可以使用任何功能吗?

3 个答案:

答案 0 :(得分:1)

有lsof工具执行此操作,您也可以使用/ proc / filsystem查看此处,如此处所示。 How to use lsof(List Opened Files) in a C/C++ application?

答案 1 :(得分:1)

查看/proc的两种方法,你可以找到它,但你需要使用你想知道的inode grep。在下面的例子中,检查inode的最后一列。

$ cat /proc/net/tcp 
sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode      


方括号中指定的值再次为inode。

$ls -l /proc/5267/fd/10
lrwx------ 1 esunboj egi 64 Feb 18 12:07 /proc/5267/fd/10 -> socket:[19950]

答案 2 :(得分:0)

我查看了 ss 工具实现,以了解当我们使用 -p 命令行选项时它们如何获取信息。

事实是他们使用以下函数读取用户条目并生成相应的映射。然后在显示socket列表时,他们会检查map,看是否能找到inode,如果能,他们就有PID。

注意下面的函数需要root用户才能找到所有的inode。它检测名称格式为 socket:[<inode>] 的文件(/proc/<pid>/fd/<number> 下的文件是软链接,尝试使用 ls -l ... 列出它们以查看特殊套接字和 FIFO 条目)。

static void user_ent_hash_build(void)
{
    const char *root = getenv("PROC_ROOT") ? : "/proc/";
    struct dirent *d;
    char name[1024];
    int nameoff;
    DIR *dir;
    char *pid_context;
    char *sock_context;
    const char *no_ctx = "unavailable";
    static int user_ent_hash_build_init;

    /* If show_users & show_proc_ctx set only do this once */
    if (user_ent_hash_build_init != 0)
        return;

    user_ent_hash_build_init = 1;

    strlcpy(name, root, sizeof(name));

    if (strlen(name) == 0 || name[strlen(name)-1] != '/')
        strcat(name, "/");

    nameoff = strlen(name);

    dir = opendir(name);
    if (!dir)
        return;

    while ((d = readdir(dir)) != NULL) {
        struct dirent *d1;
        char process[16];
        char *p;
        int pid, pos;
        DIR *dir1;
        char crap;

        if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1)
            continue;

        if (getpidcon(pid, &pid_context) != 0)
            pid_context = strdup(no_ctx);

        snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid);
        pos = strlen(name);
        if ((dir1 = opendir(name)) == NULL) {
            free(pid_context);
            continue;
        }

        process[0] = '\0';
        p = process;

        while ((d1 = readdir(dir1)) != NULL) {
            const char *pattern = "socket:[";
            unsigned int ino;
            char lnk[64];
            int fd;
            ssize_t link_len;
            char tmp[1024];

            if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
                continue;

            snprintf(name+pos, sizeof(name) - pos, "%d", fd);

            link_len = readlink(name, lnk, sizeof(lnk)-1);
            if (link_len == -1)
                continue;
            lnk[link_len] = '\0';

            if (strncmp(lnk, pattern, strlen(pattern)))
                continue;

            sscanf(lnk, "socket:[%u]", &ino);

            snprintf(tmp, sizeof(tmp), "%s/%d/fd/%s",
                    root, pid, d1->d_name);

            if (getfilecon(tmp, &sock_context) <= 0)
                sock_context = strdup(no_ctx);

            if (*p == '\0') {
                FILE *fp;

                snprintf(tmp, sizeof(tmp), "%s/%d/stat",
                    root, pid);
                if ((fp = fopen(tmp, "r")) != NULL) {
                    if (fscanf(fp, "%*d (%[^)])", p) < 1)
                        ; /* ignore */
                    fclose(fp);
                }
            }
            user_ent_add(ino, p, pid, fd,
                    pid_context, sock_context);
            free(sock_context);
        }
        free(pid_context);
        closedir(dir1);
    }
    closedir(dir);
}

因此,换句话说,事实是内核中似乎没有 PID 函数的 inode(或者最终用户无法访问它)。