proc/PID/status显示进程捕获的是哪个信号。但是,我想知道如何检查哪个处理程序正在处理信号。
例如:

void  handler1(int sigNum)
{
    if(sigNum == SIGINT)
        printf("handler1 is handling SIGINT\n");
}

void  handler2(int sigNum)
{
    if(sigNum == SIGINT)
        printf("handler2 is handling SIGINT\n");
}

void main()
{
    signal(SIGINT, handler1);
    signal(SIGINT, handler2);
    while(1);
}

main函数注册了两个信号处理程序来处理SIGINT如何知道handler1或handler2已注册为处理SIGINT并正在处理SIGINT?
我想做同样的事情就像在Solaris下的psig一样。
What is the meaning of every column when executing psig command?

最佳答案

我尝试了一个监控程序,它使用动态帮助程序库执行插入了signal()sigaction()fork()的目标进程。监视程序侦听传入的Unix域连接。
动态库非常简单。在启动时(使用Linux ELF二进制文件中支持的GCCconstructor属性),它连接到监控程序。(成功fork()后,新进程将关闭其描述符副本,并打开一个新连接。)在每次signal()sigaction()调用时,它使用

struct change {
    uint64_t      addr;
    char          name[15];
    unsigned char info;       /* SA_RESETHAND; SIG_DFL/SIG_IGN */
};

库将信号号映射到名称(如SIGINT"INT"SIGRTMIN+3"RTMIN+3")或未识别信号号的纯十进制数字字符串。这允许单个64位监视程序监视64位和32位进程的混合。
info字段用于报告SA_RESETHANDSA_ONESHOT)信号处理程序,当信号传递到处理程序时,将重置为默认配置。它还用于指示SIG_DFLSIG_IGN处理程序,以及可能的其他特殊事件。
当建立新连接时,监控程序使用readelf -W --syms --dyn-symsobjdump -tTobjdump -d打开/proc/PID/exe,记住二进制文件中每个已知函数的地址(或地址范围)。它记录每个连接的每个struct change,以及一个时间戳。
(建立连接时,插入库必须“暂停”,直到监视程序检查完二进制文件。否则,在监控程序有时间检查正确二进制之前,短运行二进制文件可能已经退出(或执行另一个二进制)。
在我的系统上,bash为地址447ad0安装SIGCHLD处理程序,该地址没有关联的符号。例如,如果已知符号按升序排序,并且处理程序是相对于最近的符号指定的,则该处理程序可以报告为reap_dead_jobs+40 <447ad0>。(注意reap_dead_jobs位于[447a90,447ac1),因此查找覆盖地址的符号是不够的。)
根据我的实验,把这看作是对应该有效的方法的描述。我自己的代码需要完全重写才能有用;这就是为什么我没有在这里包含它。我预计完成的项目大约有600-900行代码。

关于c - Linux:如何检查哪个处理程序正在处理信号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51644645/

10-11 19:42
查看更多