繁体   English   中英

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

[英]How to find the owner process of an opened inode in Linux kernel?

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

有什么我可以使用的功能吗?

有执行此操作的 lsof 工具,您也可以使用 /proc/ filsystem 看到这一点,如此处所回答。 如何在 C/C++ 应用程序中使用 lsof(List Opened Files)?

查看/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]

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

事实是,他们使用以下函数读取用户条目并生成相应的地图。 然后在显示套接字列表时,他们检查映射以查看是否可以找到 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(或者最终用户无法访问它)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM