如何从用户输入中捕获信号?

如何从用户输入中捕获信号?

我正在尝试编写一个程序来要求用户输入信号编号,然后它将调用处理程序。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void decide(int signo)
{
    printf("I received signal\n");

}

int main()
{
    int signum;

    printf("Enter Signal Number:");
    scanf("%d", &signum);

    if(signal(signum,decide) == SIG_ERR)
    {
        perror("signal");
    }

    //pause();

    printf("I hope you have a good evening!\n");

    return 0;
}

但它似乎跳过信号处理程序并始终打印最后一行。我可以更改什么以便它调用处理程序?

答案1

signal功能(可能与其名称相反)仅设置任何信号处理行为未来出现的信号:

signal()函数选择接收信号编号的三种方式之一信号 待后续处理。如果值功能为 SIG_DFL,则应对该信号进行默认处理。如果值功能为SIG_IGN,该信号将被忽略。否则,申请应确保功能指向该信号发生时要调用的函数。

您的程序设置了一个信号处理程序并检查是否没有错误 - 太棒了! - 但随后继续打印告别并立即退出,此时整个进程(包括其信号处理程序)不再存在。

环境信号处理程序是 Unix 模型中的一个不同事件接收和处理一个信号。设置处理程序后,任何将来到达的信号都将发送到该处理程序进行处理,并且程序的其余部分将继续运行。如果没有匹配的信号出现,处理程序就会安静地坐在那里,永远不需要做任何事情。


那里一个非常小的窗口,您可以在信号退出之前在其中传递信号。该窗口本质上就是您的位置pause()称呼被注释掉了 - 事实上,这几乎就是这样该函数的目的pause:

pause()函数应挂起调用线程,直到传递一个信号,该信号的操作是执行信号捕获函数或终止进程。

否则,无论是在pause微观窗口还是微观窗口中,您都可以kill -XYZ $pid从另一个终端运行您的处理程序。这是我这样做的会议:

mwh:/tmp$ ./test
Enter Signal Number:12
I received signal
I hope you have a good evening!
mwh:/tmp$

test在另一个终端中,我找到了进程的 PID ps awx,然后运行kill -12 9245。在我按下 Enter 键之前killtest进程只是坐在那里什么都不做,一旦我执行了信号处理程序,消息就会被打印、pause()返回,程序的其余部分就会运行完成。


如果你想让进程发送信号对自己出于某种原因,你也可以这样做。这raise功能天生就会这样做:

raise()函数应发送信号信号到正在执行的线程或进程。如果调用信号处理程序,则 raise() 函数应在信号处理程序返回后才返回。

所以

raise(signum);

代替pause();会起作用。

除了 SIGKILL 或其他不可捕获信号的极端情况之外,这在这里并不是非常有用,这将产生有趣的结果(尝试输入 9 和 19!)。不过,如果您正在探索信号和进程模型的工作原理,那么可能会节省一些寻找 PID 的时间和精力。

你也可以使用kill(getpid(), signum);pthread_kill(pthread_self(), sig);(其定义与 完全相同raise(signum))。

相关内容