非fork进程间设备文件描述符共享:pidfd系列系统调用的实现问询
非fork进程间设备文件描述符共享:pidfd系列系统调用的实现问询
看起来你找对路子啦!Linux 5.6版本引入的pidfd_open和pidfd_getfd这两个系统调用,确实能解决你这种非fork进程间传递文件描述符的需求,还不用依赖UNIX套接字,完美贴合你的场景。
先明确下你的核心需求:在一个进程里打开设备文件,然后在另一个完全独立的非亲缘进程中关闭这个设备描述符,对吧?你已经尝试着手写代码验证这个方案,先把你给出的open_device.c代码整理完善下:
#include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/syscall.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> // 代码里用到printf,需要补充这个头文件 #define pidfd_open(pid, flags) syscall(SYS_pidfd_open, pid, flags) int main() { // Open the device int fd = open("/dev/null", O_RDWR); if (fd == -1) { perror("open"); return EXIT_FAILURE; } printf("File descriptor for /dev/null: %d\n", fd); // Get the current process ID pid_t pid = getpid(); // Obtain a pidfd for this process int pidfd = pidfd_open(pid, 0); if (pidfd == -1) { perror("pidfd_open"); close(fd); return EXIT_FAILURE; } // 这里可以把pid或者pidfd传递给另一个进程,比如打印出来让用户手动输入,或者通过本地文件/环境变量传递 printf("Current process PID: %d, pidfd: %d\n", pid, pidfd); // 保持进程运行,等待另一个进程完成操作 pause(); close(pidfd); close(fd); return EXIT_SUCCESS; }
这里要提醒你几个关键细节,避免踩坑:
- 你提到的
pidfd_getfd调用中,第二个参数要填目标进程里实际的设备文件描述符(也就是上面代码里的fd变量),而不是固定的0——0对应的是目标进程的标准输入fd,可不是你要的设备fd哦 - 调用
pidfd_getfd的进程需要足够权限:要么和目标进程拥有相同的UID,要么具备CAP_SYS_PTRACE权限,不然会返回权限错误 - 两个进程之间需要传递PID或者pidfd:比如你可以在第一个进程里打印PID,然后在第二个进程里手动输入;或者通过本地文件、环境变量等轻量方式传递,完全不用UNIX套接字
给你补充一个对应的close_device.c示例,用来在另一个进程中获取设备fd并关闭:
#include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/syscall.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #define pidfd_open(pid, flags) syscall(SYS_pidfd_open, pid, flags) #define pidfd_getfd(pidfd, fd, flags) syscall(SYS_pidfd_getfd, pidfd, fd, flags) int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <target_pid> <target_device_fd>\n", argv[0]); return EXIT_FAILURE; } pid_t target_pid = atoi(argv[1]); int target_device_fd = atoi(argv[2]); int pidfd = pidfd_open(target_pid, 0); if (pidfd == -1) { perror("pidfd_open"); return EXIT_FAILURE; } // 从目标进程获取设备fd int device_fd = pidfd_getfd(pidfd, target_device_fd, 0); if (device_fd == -1) { perror("pidfd_getfd"); close(pidfd); return EXIT_FAILURE; } printf("Got device fd: %d, closing it...\n", device_fd); close(device_fd); close(pidfd); return EXIT_SUCCESS; }
测试的时候,先运行open_device,它会打印出设备fd和进程PID;然后另开一个终端,运行close_device <目标PID> <设备fd>,就能完成跨进程关闭设备的操作啦。
备注:内容来源于stack exchange,提问作者Droll80
相关产品推荐
相关产品推荐

