简体   繁体   中英

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

I've looked into the man pages, and there's basically nothing that explains anything, and my web searching has failed.

Man pages for pidfd_* :

I've also looked through other man pages that could have been relevant:

Update: I also tried dereferencing the /proc/self/fd/<PID_FD> symlink, but unfortunately, it just returns anon_inode:[pidfd] , which is entirely unhelpful. I initially specified that as an answer, but I later found readlink /proc/self/fd/<PID_FD> wasn't returning the same as readlink /proc/$PID/fd/<PID_FD> , and so I deleted it. If someone can help me out here, bounty's open!

Here is one implementation of 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);
}

Compile with:

gcc -o main main.c

Test with:

./main $$

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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