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

发布于 2024-08-15 10:01:29 字数 116 浏览 12 评论 0原文

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

I need to intercept and trace signals from any binaries, like strace does it under linux.
I don't need a so verbose output like the real one strace.
I just want to know how it works, how can I intercept signal and how can I trace them.
Thanks in advance :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

给我一枪 2024-08-22 10:01:29

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;
}

strace uses the ptrace() system call for tracing, which also allows you to intercept (and possibly manipulate) signals sent to the process.

Here's a tiny example:

#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;
}
羁拥 2024-08-22 10:01:29

这是一个简单的实现:

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);

This is a simple implementation:

Put somewhere in your int main() several calls to signal(), one for each signal you want to catch. The first argument is the signal name; the second is the signal handler function (more on that below):

    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

Now, write a signal function. It must return void and accept an int: void SignalHandler(int signal_number):

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

That's it! You can also test it by sending a signal to yourself with the function raise(SIGNAL_NAME); for example, try raise(SIGTERM);!

自在安然 2024-08-22 10:01:29

除了调试之外,您不应该出于任何原因拦截发送给其他进程的信号。这就是 strace 的目的。进程应该能够处理自己的信号。

不用说,如果您正在编写调试器,请了解 ptrace()。

Intercepting signals to other processes is something you should not do for any reason other than debugging them. This is what strace is intended for. Processes should be capable of handling their own signals.

Needless to say, if you are writing a debugger, understand ptrace().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文