gra*_*ity 31
两个Linux特有的方法SA_SIGINFO和signalfd(),从而允许程序接收非常约发送信号,包括发送者的PID的详细信息.
调用sigaction()并传递给它,struct sigaction其中包含所需的信号处理程序sa_sigaction和集合中的SA_SIGINFO标志sa_flags.使用此标志,您的信号处理程序将接收三个参数,其中一个参数siginfo_t包含发送方的PID和UID.
从中调用signalfd()和读取signalfd_siginfo结构(通常在某种select/poll循环中).内容类似于siginfo_t.
使用哪一个取决于您的应用程序的编写方式; 它们可能在普通C之外不能正常工作,我也没有希望让它们在Java中工作.它们在Linux之外也是不可移植的.它们也可能是你正在努力实现的非常错误的方式.
我还需要在一个程序中识别信号发送者,所以我接受了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将手动终止程序.
该程序可以成功识别谁发送了信号.