Unix-控制C和控制Z信号拾取问题
我正在试用Unix中提供的信号。我现在关注的两个是Ctrl+C和Ctrl+Z。我想捕捉信号,并在屏幕上显示一条消息。我大部分时间都在工作。与按下任一信号时显示的消息类似。然而,它似乎只起作用一次。我希望在每次按下Ctrl+C或Ctrl+Z时显示消息。像一个环Unix-控制C和控制Z信号拾取问题,c,unix,signals,C,Unix,Signals,我正在试用Unix中提供的信号。我现在关注的两个是Ctrl+C和Ctrl+Z。我想捕捉信号,并在屏幕上显示一条消息。我大部分时间都在工作。与按下任一信号时显示的消息类似。然而,它似乎只起作用一次。我希望在每次按下Ctrl+C或Ctrl+Z时显示消息。像一个环 #include <stdio.h> #include <signal.h> void handler (int signal); int main () { if (signal(SIGINT, handl
#include <stdio.h>
#include <signal.h>
void handler (int signal);
int main ()
{
if (signal(SIGINT, handler) == SIG_ERR)
{
write (2, "Error catching signal C \n",26);
}
if (signal(SIGTSTP, handler) == SIG_ERR)
{
write(2, "Error catching signal Z \n", 26);
}
pause();
}
void handler (int signal)
{
if (signal == SIGINT)
{
write(1, "CONTROLC \n", 11);
}
else if (signal == SIGTSTP)
{
write(1, "CONTROLZ \n", 11);
}
else
{
write(2, "error \n", 8);
}
main();
}
#包括
#包括
无效处理程序(int信号);
int main()
{
if(信号(SIGINT,handler)=SIG_ERR)
{
写入(2,“错误捕捉信号C\n”,26);
}
if(信号(SIGTSTP,处理程序)==SIG_ERR)
{
写入(2,“错误捕捉信号Z\n”,26);
}
暂停();
}
无效处理程序(int信号)
{
如果(信号==SIGINT)
{
写入(1,“CONTROLC\n”,11);
}
否则如果(信号==SIGTSTP)
{
写入(1,“控制Z\n”,11);
}
其他的
{
写入(2,“错误\n”,8);
}
main();
}
我试图使用main函数,以便它再次重新启动程序,但我假设它的调用main来自一个信号,因此它的行为不同?不要使用信号(2),除非可能将给定信号的配置设置为
SIG\u DFL
或SIG\u IGN
。它的行为在不同的unix之间有所不同
为了便于移植(在POSIX系统之间)和更好的控制,您应该通过sigaction(2)系统调用安装用户信号处理程序。除此之外,它允许您在安装处理程序时在一次性模式和持久模式之间进行选择
如果您有义务使用信号(2),那么您最好的选择是处理程序做的最后一件事是重新安装自己作为给定信号的处理程序(当这实际上是您想要的时候)。不要使用信号(2),除非可能将给定信号的配置设置为
SIG\u DFL
或SIG\u IGN
。它的行为在不同的unix之间有所不同
为了便于移植(在POSIX系统之间)和更好的控制,您应该通过sigaction(2)系统调用安装用户信号处理程序。除此之外,它允许您在安装处理程序时在一次性模式和持久模式之间进行选择
如果您必须使用信号(2),那么您的最佳选择是处理程序做的最后一件事是重新安装自己作为给定信号的处理程序(当这实际上是您想要的时候)。哇,不要这样做。:) 这里发生的事情是,例如,在处理程序的执行过程中,SIGINT被屏蔽(阻塞)。因此,从处理程序中重新调用
main
,将在SIGINT被阻止的情况下重新运行main
。因此,您可以看到您的处理程序在每个信号中只发射一次-之后它将被阻止。(请注意,信号
不能保证这种阻塞行为,这是您需要的原因之一。)
典型的信号处理程序应该尽可能少地工作,只使用函数(如果有的话)。将处理程序视为进程普通流的一个中断,一个特殊的异步流,如果需要,可以使用它
如果希望程序的行为类似于循环,请将其编码为循环:
static volatile sig_atomic_t flag_int;
static volatile sig_atomic_t flag_tstp;
static void handle_int(int s) { flag_int = 1; } /* register me with sigaction */
static void handle_tstp(int s) { flag_tstp = 1; } /* me, too */
...
while (1) {
pause();
if (flag_int) { printf("CONTROL C\n"); flag_int = 0; }
if (flag_tstp) { printf("CONTROL Z\n"); flag_tstp = 0; }
}
哇,别那样做。:) 这里发生的事情是,例如,在处理程序的执行过程中,SIGINT被屏蔽(阻塞)。因此,从处理程序中重新调用
main
,将在SIGINT被阻止的情况下重新运行main
。因此,您可以看到您的处理程序在每个信号中只发射一次-之后它将被阻止。(请注意,信号
不能保证这种阻塞行为,这是您需要的原因之一。)
典型的信号处理程序应该尽可能少地工作,只使用函数(如果有的话)。将处理程序视为进程普通流的一个中断,一个特殊的异步流,如果需要,可以使用它
如果希望程序的行为类似于循环,请将其编码为循环:
static volatile sig_atomic_t flag_int;
static volatile sig_atomic_t flag_tstp;
static void handle_int(int s) { flag_int = 1; } /* register me with sigaction */
static void handle_tstp(int s) { flag_tstp = 1; } /* me, too */
...
while (1) {
pause();
if (flag_int) { printf("CONTROL C\n"); flag_int = 0; }
if (flag_tstp) { printf("CONTROL Z\n"); flag_tstp = 0; }
}
不要从信号处理程序调用main(),因为您的程序现在卡在信号处理程序中,并且在处理程序运行时,它不会再次为同一信号调用另一个信号处理程序。
(如果您使用sigaction()而不是signal(),则可以更改该行为)
还可以查看pause()调用的作用
说明
pause()使调用进程(或线程)休眠,直到传递了终止进程或导致
调用信号捕获函数
所以,你的停顿();调用将等待信号发出,然后继续您的程序
因此,这样做可以保持程序运行
for(;;) {
pause();
}
不要从信号处理程序调用main(),因为您的程序现在卡在信号处理程序中,并且在处理程序运行时,它不会再次为同一信号调用另一个信号处理程序。
(如果您使用sigaction()而不是signal(),则可以更改该行为)
还可以查看pause()调用的作用
说明
pause()使调用进程(或线程)休眠,直到传递了终止进程或导致
调用信号捕获函数
所以,你的停顿();调用将等待信号发出,然后继续您的程序
因此,这样做可以保持程序运行
for(;;) {
pause();
}
很好的指导,但不能解释他看到的行为。历史行为在这里并不起作用:如果重新设置为SIG_DFL,则在第二次SIGINT的情况下会终止他的进程。你说得对,@pilcrow。我完全忽略了处理程序末尾的
main()
调用(奇怪得我的大脑拒绝了它,我猜),我没有停下来思考SIGINT
的默认处理。我删除了不正确的断言。很好的指导,但没有解释他看到的行为。历史行为在这里不起作用