简体   繁体   中英

Hi I am coding for this hw, using signal(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;

}

The requirement is to count and print the number of SIGINT signals received during the first 10 seconds, "Block" the SIGINT signal once it reaches 10 seconds of its life, "Unblock" and "Ignore" the SIGINT signal once it reaches 20 seconds of its life, terminate after 30 seconds.

Only the first 10 seconds work. The second 10 seconds seems not to count SIGINT (I'm not sure how to "ignore" the signal). The requirement is using sigaction and sigpromask .

I've fixed the issues mentioned in my top comments.

time_duration counts down from 30 to 0. But, it would be closer to the problem statement if it counted up from 0 to 30 [and makes the logic easier]. So, from here on, I'll refer to that interval

In the 10-20 interval, you setup newmask but you don't use it in sigprocmask until the 20-30 interval. I think you should use the mask immediately.

At the 20-30 interval, we have to restore the original mask, but we need another sigaction call with sa_handler set to SIG_IGN

You've got sigpending(&pendmsk); but don't do anything with it [and it's not really needed].

Because of the signal safety requirement I mentioned in my top comments, all printing should be done outside the signal handler. And, this necessitates the use of volatile on num_count [so the base level will use the most current value].


I've added a flag that allows the given action to be executed once upon entering the new interval/era.

I've added a kill syscall to simulate a user doing a ctrl-c and changed the signal to SIGTERM so a real SIGINT will terminate the program [a convenience in debugging]. You can revert this for production.

I changed some of the variable names to be more descriptive.

Here's the refactored code:

#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, &act, NULL);
                sigprocmask(SIG_SETMASK, &oldmask, NULL);
            }
            break;
        }

        interval_count[time_switch] = curstate + 1;

        if (time_duration > 30)
            break;
    }

    return 0;
}

Here's the program output:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM