PIDFD_SEND_SIGNAL - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
pidfd_send_signal-向文件描述符指定的进程发送信号
语法
#include <signal.h> int pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags);
说明
pidfd_send_signal()系统调用将信号sig发送到pidfd所引用的目标进程,pidfd是引用进程的PID文件描述符。
如果info参数指向siginfo_t缓冲区,则应按照rt_sigqueueinfo(2)中的说明填充该缓冲区。
如果info参数是NULL指针,则等效于指定指向siginfo_t缓冲区的指针,该缓冲区的字段与使用kill(2)发送信号时隐式提供的值匹配:
- *
- si_signo设置为信号编号;
- *
- si_errno设置为0;
- *
- si_code设置为SI_USER;
- *
- si_pid设置为调用者的PID;和
- *
- si_uid设置为调用者的真实用户ID。
调用进程必须与pidfd所指的进程位于同一PID名称空间中,或者必须位于该名称空间的祖先中。
flags参数保留供将来使用。当前,此参数必须指定为0。
返回值
成功时,pidfd_send_signal()返回0。错误时,返回-1并设置errno以指示错误原因。
错误说明
- EBADF
- pidfd不是有效的PID文件描述符。
- EINVAL
- sig不是有效信号。
- EINVAL
- 调用进程不在PID命名空间中,它可以从该命名空间向目标进程发送信号。
- EINVAL
- 标志不为0。
- EPERM
- 调用进程无权将信号发送到目标进程。
- EPERM
- pidfd没有引用调用过程,并且info.si_code无效(请参阅rt_sigqueueinfo(2))。
- ESRCH
- 目标进程不存在(即已终止并等待)。
版本
pidfd_send_signal()最早出现在Linux 5.1中。
遵循规范
pidfd_send_signal()是Linux特定的。
备注
当前,此系统调用没有glibc包装器。使用syscall(2)调用它。
PID file descriptors
pidfd参数是PID文件描述符,它是引用进程的文件描述符。可以通过以下任何一种方式获得这种文件描述符:
- *
- 通过打开/ proc / [pid]目录;
- *
- 使用pidfd_open(2);要么
- *
- 通过对指定CLONE_PIDFD标志的clone(2)或clone3(2)的调用返回的PID文件描述符。
系统调用pidfd_send_signal()可以避免使用传统接口(例如kill(2))发信号通知进程时发生的竞争情况。问题在于传统接口通过进程ID(PID)指定目标进程,结果是,如果最初打算的目标进程已终止并且其PID已被回收用于另一个进程,则发送方可能会意外地将信号发送给错误的进程处理。相比之下,PID文件描述符是对特定过程的稳定引用。如果该进程终止,则pidfd_send_signal()失败,并显示错误ESRCH。
示例
#define _GNU_SOURCE #include <limits.h> #include <signal.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/syscall.h> #ifndef __NR_pidfd_send_signal #define __NR_pidfd_send_signal 424 #endif static int pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) { return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); } int main(int argc, char *argv[]) { siginfo_t info; char path[PATH_MAX]; int pidfd, sig; if (argc != 3) { fprintf(stderr, "Usage: %s <pid> <signal>\n", argv[0]); exit(EXIT_FAILURE); } sig = atoi(argv[2]); /* Obtain a PID file descriptor by opening the /proc/PID directory of the target process */ snprintf(path, sizeof(path), "/proc/%s", argv[1]); pidfd = open(path, O_RDONLY); if (pidfd == -1) { perror("open"); exit(EXIT_FAILURE); } /* Populate a aqsiginfo_taq structure for use with pidfd_send_signal() */ memset(&info, 0, sizeof(info)); info.si_code = SI_QUEUE; info.si_signo = sig; info.si_errno = 0; info.si_uid = getuid(); info.si_pid = getpid(); info.si_value.sival_int = 1234; /* Send the signal */ if (pidfd_send_signal(pidfd, sig, &info, 0) == -1) { perror("pidfd_send_signal"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
另外参见
clone(2),kill(2),pidfd_open(2),rt_sigqueueinfo(2),sigaction(2),pid_namespaces(7),signal(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。