PIDFD_SEND_SIGNAL - Linux手册页

时间:2019-08-20 17:59:07  来源:igfitidea点击:

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/