关于捕捉Unix信号的问题

关于捕捉Unix信号的问题,unix,signals,Unix,Signals,以下代码仅捕获一次SIGINT信号,然后中断程序存在: #include <signal.h> #include <stdio.h> void IntHandler(int value); void CatchIntSignal() { struct sigaction intAction; intAction.sa_handler = IntHandler; sigemptyset(&intAction.sa_mask); i

以下代码仅捕获一次SIGINT信号,然后中断程序存在:

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

void IntHandler(int value);

void CatchIntSignal()
{
    struct sigaction intAction;
    intAction.sa_handler = IntHandler;
    sigemptyset(&intAction.sa_mask);
    intAction.sa_flags = 0;
    //if to uncomment any of "0" or "SIG_IGN" - IntHandler will be never called:
    //intAction.sa_sigaction = 0/*SIG_IGN*/;
    if(sigaction(SIGINT, &intAction, NULL) != 0)
    {
        printf("sigaction() failed.\n");
    }
}

void IntHandler(int value)
{
    printf("IntHandler(%d)\n", value);
    //uncommenting this does not help:
    //CatchIntSignal();
}

int main()
{
    CatchIntSignal();
    getchar();
    return 0;
}
我必须如何修改此代码以在SIGINT捕获后保留程序的退出?
如果要将intAction.sa_sigaction设置为0或SIG_IGN,则永远不会调用IntHandler-但为什么?它必须告诉系统有必要调用IntHandler的哪个未定义值?如果我将某个处理程序设置为intAction.sa_sigaction-将调用此处理程序,但不会调用IntHandler。系统如何知道我设置了intAction.sa_sigaction?

捕获中断信号并在捕获代码中处理后,需要将处理设置回SIG_DFL


编辑:请忽略。这仅适用于旧的unix信号

捕获中断信号并在捕获代码中进行处理后,需要将处理设置回SIG_DFL

编辑:请忽略。这仅适用于旧的unix信号

您的问题是struct sigaction的sa_处理程序和sa_sigaction字段实际上是同一个字段。引用sigaction2的OSX手册页:

因此,对sau sigaction的赋值将覆盖已设置的处理程序。您应该只设置sau处理程序,而不使用sau sigaction。以下是CatchIntSignal的内容:

void CatchIntSignal()
{
    struct sigaction intAction;
    intAction.sa_handler = IntHandler;
    sigemptyset(&intAction.sa_mask);
    intAction.sa_flags = SA_RESTART;
    if(sigaction(SIGINT, &intAction, NULL) != 0)
        printf("sigaction() failed: %s\n", strerror(errno));
}
您可能需要添加string.h和errno.h的include以获得要编译的strerrorno位。在系统调用失败时触发的错误消息中始终包含strerrorno

更正:在每个ninjalj的标志中添加了SA_RESTART。

您的问题是struct sigaction的SA_处理程序和SA_sigaction字段实际上是同一个字段。引用sigaction2的OSX手册页:

因此,对sau sigaction的赋值将覆盖已设置的处理程序。您应该只设置sau处理程序,而不使用sau sigaction。以下是CatchIntSignal的内容:

void CatchIntSignal()
{
    struct sigaction intAction;
    intAction.sa_handler = IntHandler;
    sigemptyset(&intAction.sa_mask);
    intAction.sa_flags = SA_RESTART;
    if(sigaction(SIGINT, &intAction, NULL) != 0)
        printf("sigaction() failed: %s\n", strerror(errno));
}
您可能需要添加string.h和errno.h的include以获得要编译的strerrorno位。在系统调用失败时触发的错误消息中始终包含strerrorno


更正:为每个ninjalj的标志添加了SA_RESTART。

您的问题可能是系统调用被中断,因此getchar返回,可能带有EOF。接下来程序要做的就是退出


因此,您可以尝试检查getchar返回的内容,在stdin上重置错误状态,然后再次调用getchar以获取下一个信号。

您的问题可能是系统调用被中断,因此getchar返回,可能带有EOF。接下来程序要做的就是退出


因此,您可以尝试检查getchar返回的内容,重置stdin上的错误状态,然后再次调用getchar以获取下一个信号。

我不明白您希望程序做什么。是:第一次接收到SIGINT时,调用IntHandler,然后程序退出?或者是:每次接收到SIGINT时,都会调用IntHandler;在getchar返回之前,程序不会退出?我希望这样,我的程序将捕获SIGINT信号,并且在它之后不会退出。这样,在每次Ctrl+C之后,程序都会打印IntHandler2并继续工作。我不明白您希望程序做什么。是:第一次接收到SIGINT时,调用IntHandler,然后程序退出?或者是:每次接收到SIGINT时,都会调用IntHandler;在getchar返回之前,程序不会退出?我希望这样,我的程序将捕获SIGINT信号,并且在它之后不会退出。这样,在每个Ctrl+C程序之后,都会打印IntHandler2并继续工作;这是sigaction优于signal的主要优点。若使用信号,你们将更接近正确。处理程序将自动重置为SIG_DFL,并且有必要在处理程序中重置处理程序。不使用sigaction;这是sigaction优于signal的主要优点。若使用信号,你们将更接近正确。处理程序将自动重置为SIG_DFL,并且有必要在处理程序中重置处理程序。因此OP应该在SA_标志上设置SA_重启,或者在getchar失败时检查EINTR。是的,确实如此。谢谢你,艾伊!我应该记得萨乌。谢谢你指出ninjalj。@Zack,@ninjali-我也应该记得SA_重启。所以OP应该在SA_标志上设置SA_重启,或者在getchar失败时检查EINTR。是的,确实如此。谢谢你,艾伊!我应该记得萨乌。谢谢你指出ninjalj.@Zack,@ninjali-我也应该记得SA_RESTART.Union。。。你向我透露了真相。非常感谢。协会你向我透露了真相。非常感谢。