![如何从用户输入中捕获信号?](https://linux22.com/image/149505/%E5%A6%82%E4%BD%95%E4%BB%8E%E7%94%A8%E6%88%B7%E8%BE%93%E5%85%A5%E4%B8%AD%E6%8D%95%E8%8E%B7%E4%BF%A1%E5%8F%B7%EF%BC%9F%20.png)
我正在尝试编写一个程序来要求用户输入信号编号,然后它将调用处理程序。
#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 键之前kill
,test
进程只是坐在那里什么都不做,一旦我执行了信号处理程序,消息就会被打印、pause()
返回,程序的其余部分就会运行完成。
如果你想让进程发送信号对自己出于某种原因,你也可以这样做。这raise
功能天生就会这样做:
该
raise()
函数应发送信号信号到正在执行的线程或进程。如果调用信号处理程序,则 raise() 函数应在信号处理程序返回后才返回。
所以
raise(signum);
代替pause();
会起作用。
除了 SIGKILL 或其他不可捕获信号的极端情况之外,这在这里并不是非常有用,这将产生有趣的结果(尝试输入 9 和 19!)。不过,如果您正在探索信号和进程模型的工作原理,那么可能会节省一些寻找 PID 的时间和精力。
你也可以使用kill(getpid(), signum);
或pthread_kill(pthread_self(), sig);
(其定义与 完全相同raise(signum)
)。