我查看了手册页,基本上没有任何解释,我的网络搜索失败了。
pidfd_*
的手册页:
pidfd_open
系统调用:https://man7.org/linux/man-pages/man2/pidfd_open.2.htmlpidfd_send_signal
系统调用:https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.htmlpidfd_getfd
系统调用:https://man7.org/linux/man-pages/man2/pidfd_getfd.2.html我还浏览了其他可能相关的手册页:
clone3
系统调用:https://man7.org/linux/man-pages/man2/clone3.2.htmlwaitid
系统调用:https://man7.org/linux/man-pages/man2/waitid.2.htmlpoll
系统调用:https://man7.org/linux/man-pages/man2/poll.2.htmlselect
系统调用: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>
相同的结果,所以我删除了它。如果有人可以帮助我,赏金开放!
/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 $$
使用新的 ioctl(..PIDFD_INFO_PID) 是可能的,但内核 6.12 仍在开发中。