繁体   English   中英

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

[英]Given a PID FD (as acquired from `pidfd_open`), how does one get the underlying PID for it?

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

pidfd_*的手册页:

  • pidfd_open系统调用: https ://man7.org/linux/man-pages/man2/pidfd_open.2.html
  • pidfd_send_signal系统调用: https ://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html
  • pidfd_getfd系统调用: https ://man7.org/linux/man-pages/man2/pidfd_getfd.2.html

我还查看了其他可能相关的手册页:

  • clone3系统调用: https ://man7.org/linux/man-pages/man2/clone3.2.html
  • procfs: https://man7.org/linux/man-pages/man5/procfs.5.html
  • waitid系统调用: https ://man7.org/linux/man-pages/man2/waitid.2.html
  • poll系统调用: https ://man7.org/linux/man-pages/man2/poll.2.html
  • select系统调用: https ://man7.org/linux/man-pages/man2/select.2.html

更新:我还尝试取消引用/proc/self/fd/<PID_FD>符号链接,但不幸的是,它只返回anon_inode:[pidfd] ,这完全没有帮助。 我最初将其指定为答案,但后来发现readlink /proc/self/fd/<PID_FD>返回的结果与readlink /proc/$PID/fd/<PID_FD> ,因此我将其删除。 如果有人可以帮助我,赏金开放!

这是 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 $$

暂无
暂无

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

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