如何拦截linux信号? (在C)

我需要拦截和跟踪来自任何二进制文件的信号,比如strace在linux下。 我不需要像真正的strace那样输出如此冗长的输出。 我只是想知道它是如何工作的,我怎样才能拦截信号,怎样才能追踪它们。 提前致谢 :)

strace使用ptrace()系统调用进行跟踪,这也允许您截取(并可能操纵)发送到进程的信号。

这是一个小例子:

 #include <sys/ptrace.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { /* simple example, child is traced, uses alarm which causes a signal to be * set up */ pid_t child; child = fork(); if (child == 0) { ptrace(PTRACE_TRACEME, 0, NULL, NULL); alarm(3); while(1) { } exit(0); } /* parent */ while(1) { int wstatus; int signum; wait(&wstatus); if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus)) break; signum = WSTOPSIG(wstatus); printf("child stopped with signal %d\n", signum); /* resume execution */ ptrace(PTRACE_CONT, child, NULL, signum); } return 0; } 

这是最简单的实现!

放在你的int main()几个调用signal() ,每一个你想要捕捉的信号。 第一个参数是信号名称; 第二个是信号处理函数(更多关于下面的内容):

  signal(SIGFPE, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGINT, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGTERM, SignalHandler); #ifndef WIN32 signal(SIGHUP, SignalHandler); signal(SIGQUIT, SignalHandler); signal(SIGKILL, SignalHandler); signal(SIGPIPE, SignalHandler); signal(SIGCHLD, SignalHandler); #endif 

现在,写一个信号功能。 它必须返回void并接受一个int: void SignalHandler(int signal_number)

 void SignalHandler(int signal_number) { printf("Received signal: %s\n", strsignal(signal_number); // Do something } 

而已! 您也可以通过函数raise(SIGNAL_NAME)向自己发送一个信号来测试它; 例如,尝试raise(SIGTERM);

截取到其他进程的信号是除了调试以外的任何其他原因。 这是strace的目的。 进程应该能够处理自己的信号。

不用说,如果你正在编写一个调试器,理解ptrace()。