C 检查发送到应用程序的最后一个信号

C 检查发送到应用程序的最后一个信号,c,linux,unix,signals,C,Linux,Unix,Signals,我希望在发送信号时能够打破while循环。我不确定如何在不使用全局变量或不写入文件的情况下实现这一点。我的最佳选择是使用信号灯吗 #include <stdio.h> #include <signal.h> void random() { printf("random!"); } int main(void) { signal(SIGINT, random); // I want this while loop to break if ran

我希望在发送信号时能够打破while循环。我不确定如何在不使用全局变量或不写入文件的情况下实现这一点。我的最佳选择是使用信号灯吗

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

void random()
{
    printf("random!");
}

int main(void) {
    signal(SIGINT, random);

    // I want this while loop to break if random executes
    while (1)
    {
        pause();
    }
    // do more stuff after loop

    return 0;
}
#包括
#包括
void random()
{
printf(“随机!”);
}
内部主(空){
信号(SIGINT,随机);
//如果随机执行,我希望这个while循环中断
而(1)
{
暂停();
}
//循环后做更多的事情
返回0;
}

循环结束后,您的主函数除了退出外,没有执行任何操作。我理解这可能是简单的问题代码。但是,如果您在想要中断的循环之后实际上没有做任何事情,那么只需将sig处理程序函数更改为:

void random(int sig)
{
    printf("random!");
    exit(sig);  // or exit(0); as in your main()
}

另一方面,如果您需要在
random
(处理程序)和
main
之间进行通信,那么为什么不愿意使用变量呢?

暂停
块,直到收到调用信号处理程序的信号,这样您就可以添加一个
中断
暂停()之后
退出循环。因此,您最好完全摆脱循环

如果您想做的不是等待,而是循环执行某项操作并仅在信号出现时退出,则不能使用
pause
。显而易见的方法是使用一个全局变量,但您说您希望避免这种情况。另一种并不简单的方法是使用
sigprocmask
/
sigpending
代替信号处理程序:

int main()
{
    setset_t  signals;
    sigemptyset(&signals);
    sigaddset(&signals, SIGINT);
    sigprocmask(SIG_BLOCK, &signals, 0);  /* block SIGINT */

    while (1) {
        /* do stuff */
        sigpending(&signals);
        if (sigismember(&signals, SIGINT)) {
            /* got a SIGINT */
            break;
        }
    }
}

正确的答案实际上取决于你在循环中要做什么。我假设
pause()
只是一个伪代码,因为它没有用处

如果您的循环是使用
select
poll
等待的事件循环,那么您可以切换到
pselect
(POSIX中的标准)或
ppoll
(非标准扩展,但更好,因为
select
API非常糟糕),这样也可以让您等待信号。但是,您仍然需要了解如何获得信号发生的通知。仅使用一个信号,您就可以使用
EINTR
返回的事实来推断发生了
SIGINT
,但如果可能还有其他信号处理程序,这就不太好了。基本上,信号处理基本上是全局的,因此,必须以某种方式涉及全局变量/全局状态。您可以将信号发生的标志存储在全局变量中,并在每次
pselect
/
ppoll
返回时检查它,您可以只使用普通标准的
poll
并使用,因为您无论如何都需要在信号处理程序中对全局状态执行操作


如果循环不是在等待事件,而是在不断旋转(例如,一个计算循环),则只需阻塞信号(使用
sigprocmask
pthread\u sigmask
)使用
sigispending
sigwaitinfo
定期检查它是一个简单的解决方案,不需要在信号处理程序中使用任何代码。

在这种特定情况下,只需删除循环即可。不过,我希望程序在循环后继续执行,谢谢。