如何在Linux中告诉哪个进程向我的进程发送了一个信号

osh*_*hai 27 linux signals

我有一个java应用程序SIG TERM.我想知道发送此信号的进程的pid.
那可能吗?

gra*_*ity 31

两个Linux特有的方法SA_SIGINFOsignalfd(),从而允许程序接收非常约发送信号,包括发送者的PID的详细信息.

  • 调用sigaction()并传递给它,struct sigaction其中包含所需的信号处理程序sa_sigaction和集合中的SA_SIGINFO标志sa_flags.使用此标志,您的信号处理程序将接收三个参数,其中一个参数siginfo_t包含发送方的PID和UID.

  • 从中调用signalfd()和读取signalfd_siginfo结构(通常在某种select/poll循环中).内容类似于siginfo_t.

使用哪一个取决于您的应用程序的编写方式; 它们可能在普通C之外不能正常工作,我也没有希望让它们在Java中工作.它们在Linux之外也是不可移植的.它们也可能是你正在努力实现的非常错误的方式.

  • 提到的第一个方法(sigaction/SA_SIGINFO/siginfo_t)实际上是POSIX标准,并且在Mac OS,FreeBSD,OpenBSD上也支持,而不仅仅是Linux. (2认同)
  • 请注意,发送者的 pid 并不总是已设置。不幸的是,字段“si_pid”位于联合体中,因此当您“认为”正在读取 pid 时,您实际上可能会读取完全不同的内容。例如,当您的程序出现段错误时,“SIGSEGV”信号没有“si_pid”。“si_pid”是否可以安全访问在“man sigaction”中描述。如果你有 `si_code == SI_USER || si_code == SI_QUEUE` 然后设置 `si_pid`。否则事情会变得复杂。 (2认同)

Eri*_*ang 9

我还需要在一个程序中识别信号发送者,所以我接受了grawity的答案,并在我的程序中使用它,它运行良好.

这是示例代码:

send_signal_raise.c

// send signal to self test - raise()

#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

static int int_count = 0, max_int = 5;
static struct sigaction siga;

static void multi_handler(int sig, siginfo_t *siginfo, void *context) {
    // get pid of sender,
    pid_t sender_pid = siginfo->si_pid;

    if(sig == SIGINT) {
        int_count++;
        printf("INT(%d), from [%d]\n", int_count, (int)sender_pid);
        return;
    } else if(sig == SIGQUIT) {
        printf("Quit, bye, from [%d]\n", (int)sender_pid);
        exit(0);
    }

    return;
}

int raise_test() {
    // print pid
    printf("process [%d] started.\n", (int)getpid());

    // prepare sigaction
    siga.sa_sigaction = *multi_handler;
    siga.sa_flags |= SA_SIGINFO; // get detail info

    // change signal action,
    if(sigaction(SIGINT, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }
    if(sigaction(SIGQUIT, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }

    // use "ctrl + c" to send SIGINT, and "ctrl + \" to send SIGQUIT,
    int sig;
    while(1) {
        if(int_count < max_int) {
            sig = SIGINT;
        } else {
            sig  = SIGQUIT;
        }
        raise(sig); // send signal to itself,

        sleep(1); // sleep a while, note that: SIGINT will interrupt this, and make program wake up,
    }

    return 0;
}

int main(int argc, char *argv[]) {
    raise_test();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译:

gcc -pthread -Wall send_signal_raise.c

执行:

./a.out

它能做什么:

程序SIGINT在发送SIGQUIT终止之前发送10次自身.

此外,在执行期间,按CTRL+ C发送SIGINT,或CTRL+ \发送SIGQUIT将手动终止程序.

该程序可以成功识别谁发送了信号.