嗨,我正在为此硬件编码,使用信号sigaction,sigprocmask

问题描述

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

unsigned time_duration;
int num_count=0;

void sig_handling(int sig){
    if(sig==SIGINT){
        num_count++;
        printf("The number of SIGINT signals are %d\n",num_count);
    }
 } 


int main(int argc,char *argv[])
{
    unsigned time_stamp1=(unsigned)time(NULL);
    time_stamp1=time_stamp1+30;
    sigset_t newmask;
    sigset_t oldmask;
    sigset_t pendmask;
    struct sigaction act;
    act.sa_handler=&sig_handling;
act.sa_flags=SA_RESTART;
sigaction(SIGINT,&act,NULL);
while(1){
    unsigned time_stamp2=(unsigned)time(NULL);
    time_duration=time_stamp1-time_stamp2;
    if(time_duration>20&&time_duration<30)
    {
        sigemptyset(&newmask);
        sigaddset(&newmask,SIGINT);
    }
    if(time_duration>10&&time_duration<20)
    {
        sigprocmask(SIG_BLOCK,&newmask,&oldmask);
    }
    if(time_duration>0&&time_duration<10)
    {
        sigpending(&pendmask);
        sigprocmask(SIG_SETMASK,&oldmask,NULL);
        
    }
    if(time_duration==0)
    {
        break;
    }
}
return 0;

}

要求是计算并打印在前 10 秒内收到的 SIGINT 信号的数量,一旦 SIGINT 信号达到其生命周期的 10 秒,就“阻止”它,一旦达到“解除阻止”并“忽略”SIGINT 信号其生命周期为 20 秒,30 秒后终止。

只有前 10 秒有效。第二个 10 秒似乎不算 SIGINT(我不确定如何“忽略”信号)。要求使用 sigactionsigpromask

解决方法

我已经修复了我的热门评论中提到的问题。

time_durationdown 从 30 计数到 0。但是,如果它从 0 up 计数 从 0 到 30 [并且使逻辑更容易]。所以,从这里开始,我会参考那个区间

在 10-20 间隔中,您设置了 newmask,但直到 20-30 间隔才在 sigprocmask 中使用它。我认为你应该立即使用面膜。

在 20-30 的间隔,我们必须恢复原始掩码,但我们需要另一个 sigaction 调用并将 sa_handler 设置为 SIG_IGN

你有 sigpending(&pendmsk); 但不要用它做任何事情[而且它不是真的需要]。

由于我在最重要的评论中提到的信号安全要求,所有打印都应该在信号处理程序之外完成。并且,这需要在 volatile 上使用 num_count [因此基础级别将使用最新值]。


我添加了一个标志,允许在进入新的时间间隔/时代时一次执行给定的操作。

我添加了一个 kill 系统调用来模拟用户执行 ctrl-c 并将信号更改为 SIGTERM 因此真正的 SIGINT 将终止程序 [方便在调试]。您可以将其还原为生产。

为了更具描述性,我更改了一些变量名称。

这是重构后的代码:

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

time_t time_duration;
volatile long long num_count = 0;

#define SIGSELF     SIGTERM

void
sig_handling(int sig)
{
    if (sig == SIGSELF) {
        num_count++;
#if 0
        printf("The number of SIGINT signals are %d\n",num_count);
#endif
    }
}

int
main(int argc,char **argv)
{

    time_t time_begin = time(NULL);

    sigset_t newmask;
    sigset_t oldmask;
    struct sigaction act;

#if 1
    sigaction(SIGSELF,NULL,&act);
#endif
    act.sa_handler = sig_handling;
    act.sa_flags = SA_RESTART;
    sigaction(SIGSELF,&act,NULL);

    pid_t pid = getpid();
    time_t time_msg = -1;

    long long kill_count = 0;

    int interval_count[10] = { 0 };

    while (1) {
        kill(pid,SIGSELF);
        ++kill_count;

        time_t time_current = time(NULL);
        time_duration = time_current - time_begin;

        if (time_duration != time_msg) {
            time_msg = time_duration;
            printf("At %ld seconds the number of signals are %lld",time_duration,num_count);
            printf(" (kills %lld)",kill_count);
            printf("\n");
        }

        time_t time_switch = time_duration / 10;

        int curstate = interval_count[time_switch];

        if (curstate == 0)
            printf("New interval %ld\n",time_switch);

        switch (time_switch) {
        case 0:  // 0-10
            break;

        case 1:  // 10-20
            if (curstate == 0) {
                sigemptyset(&newmask);
                sigaddset(&newmask,SIGSELF);
                sigprocmask(SIG_BLOCK,&newmask,&oldmask);
            }
            break;

        case 2:  // 20-30
            if (curstate == 0) {
                act.sa_handler = SIG_IGN;
                sigaction(SIGSELF,NULL);
                sigprocmask(SIG_SETMASK,&oldmask,NULL);
            }
            break;
        }

        interval_count[time_switch] = curstate + 1;

        if (time_duration > 30)
            break;
    }

    return 0;
}

这是程序输出:

At 0 seconds the number of signals are 1 (kills 1)
New interval 0
At 1 seconds the number of signals are 487973 (kills 487973)
At 2 seconds the number of signals are 1021629 (kills 1021629)
At 3 seconds the number of signals are 1560710 (kills 1560710)
At 4 seconds the number of signals are 2100419 (kills 2100419)
At 5 seconds the number of signals are 2647694 (kills 2647694)
At 6 seconds the number of signals are 3192151 (kills 3192151)
At 7 seconds the number of signals are 3731573 (kills 3731573)
At 8 seconds the number of signals are 4273751 (kills 4273751)
At 9 seconds the number of signals are 4817509 (kills 4817509)
At 10 seconds the number of signals are 5360348 (kills 5360348)
New interval 1
At 11 seconds the number of signals are 5360348 (kills 6948004)
At 12 seconds the number of signals are 5360348 (kills 8523401)
At 13 seconds the number of signals are 5360348 (kills 10074263)
At 14 seconds the number of signals are 5360348 (kills 11432598)
At 15 seconds the number of signals are 5360348 (kills 12950546)
At 16 seconds the number of signals are 5360348 (kills 14533591)
At 17 seconds the number of signals are 5360348 (kills 15990611)
At 18 seconds the number of signals are 5360348 (kills 17410250)
At 19 seconds the number of signals are 5360348 (kills 18986650)
At 20 seconds the number of signals are 5360348 (kills 20552985)
New interval 2
At 21 seconds the number of signals are 5360348 (kills 22138819)
At 22 seconds the number of signals are 5360348 (kills 23743963)
At 23 seconds the number of signals are 5360348 (kills 25265593)
At 24 seconds the number of signals are 5360348 (kills 26802154)
At 25 seconds the number of signals are 5360348 (kills 28349228)
At 26 seconds the number of signals are 5360348 (kills 29926249)
At 27 seconds the number of signals are 5360348 (kills 31509756)
At 28 seconds the number of signals are 5360348 (kills 33100829)
At 29 seconds the number of signals are 5360348 (kills 34688121)
At 30 seconds the number of signals are 5360348 (kills 36274367)
New interval 3
At 31 seconds the number of signals are 5360348 (kills 37870874)