给定一个 PID FD(从 `pidfd_open` 获取),如何获取它的底层 PID?

问题描述 投票:0回答:2

我查看了手册页,基本上没有任何解释,我的网络搜索失败了。

pidfd_*
的手册页:

我还浏览了其他可能相关的手册页:

更新:我还尝试取消引用

/proc/self/fd/<PID_FD>
符号链接,但不幸的是,它只返回
anon_inode:[pidfd]
,这完全没有帮助。我最初指定它作为答案,但后来发现
readlink /proc/self/fd/<PID_FD>
没有返回与
readlink /proc/$PID/fd/<PID_FD>
相同的结果,所以我删除了它。如果有人可以帮助我,赏金开放!

linux process system-calls file-descriptor
2个回答
1
投票

/proc/self/fdinfo 包含当前进程打开的所有文件描述符的信息。

例如,如果pidfd为3,则

cat /proc/self/fdinfo/3
可以给出以下信息:

    pos:    0
    flags:  02000002
    mnt_id: 15
    ino:    8404
    Pid:    440
    NSpid:  440

其中 Pid 就是我们要寻找的。

这是 get_pid_for_pidfd 的一种实现

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
#define ENOENT 2
#define ERANGE 34
int errno;
static int parse_pid(const char *str, pid_t *pid) {
    unsigned long long int v; char *end; pid_t p;
    errno = 0;
    v = strtoull(str, &end, 0);
    if (end == str) return -ENOENT;
    else if (errno != 0) return -errno;
    p = (pid_t)v;
    if (p < 1 || (unsigned long long int)p != v) return -ERANGE;
    if (pid) *pid = p;
    return 0;
}
static int parse_status_field_pid(const char *val, pid_t *pid) {
    const char *t = strrchr(val, '\t');
    if (t == NULL) return -ENOENT;
    return parse_pid(t, pid);
}
static int get_pid_for_pidfd(int pidfd, pid_t *pid) {
    char *key = NULL; char *val = NULL; char name[256] = { 0, }; int found = 0;
    FILE *f = NULL; size_t keylen = 0; size_t vallen = 0; ssize_t n; int fd; int r = 0;
    int fdinfo = open("/proc/self/fdinfo", O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
    *pid = 0;
    snprintf(name, 256, "%d", pidfd);
    fd = openat(fdinfo, name, O_RDONLY | O_CLOEXEC | O_NOCTTY);
    if (fd != -1) f = fdopen(fd, "r");
    if (f == NULL) return -errno;
    do { n = getdelim(&key, &keylen, ':', f);
        if (n == -1) { r = errno; break; }
        n = getdelim(&val, &vallen, '\n', f);
        if (n == -1) { r = errno; break; }
        if (!strncmp(key, "Pid", 3)) { r = parse_status_field_pid(val, pid); found = r > -1; }
    } while (r == 0 && !found);
    fclose(f);
    if (r < 0) return r; else if (!found) return -ENOENT;
    return 0;
}
int main(int argc, char *argv[]) {
    int pidfd; pid_t pid;
    pidfd = syscall(SYS_pidfd_open, atoi(argv[1]), 0);
    if (pidfd == -1) { perror("pidfd_open"); exit(EXIT_FAILURE); }
    if (get_pid_for_pidfd(pidfd, &pid) == 0)
       printf("Input PID is %s, PID returned by get_pid_for_pidfd is %d\n", argv[1], pid);
}

编译:

gcc -o main main.c

测试:

./main $$

0
投票

使用新的 ioctl(..PIDFD_INFO_PID) 是可能的,但内核 6.12 仍在开发中。

© www.soinside.com 2019 - 2024. All rights reserved.