C Programming System Calls

How to use SIGALRM and alarm function in C language?

The alarm() function is used to generate a SIGALRM signal after a specified amount of time elapsed. In this article, we are going to show you how to use alarm() function and SIGALRM signal in Linux. So, let’s get started.

Syntax

unsigned int alarm(unsigned int seconds)

The function is defined in unistd.h header file.

Arguments

The function takes one argument, seconds. After seconds seconds have elapsed since requesting the alarm() function, the SIGALRM signal is generated. The default behavior on receipt of SIGALRM is to terminate the process. But, we can catch and handle the signal. See signal handling details.

The alarm() function will return a non zero value, if another alarm has been previously set and the value is the number of seconds remaining for the previous scheduled alarm due to delivered. Otherwise alarm() will return zero.

Example1.c:

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
 
void sig_handler(int signum){
 
  printf("Inside handler function\n");
}
 
int main(){
 
  signal(SIGALRM,sig_handler); // Register signal handler
 
  alarm(2);  // Scheduled alarm after 2 seconds
 
  for(int i=1;;i++){
 
    printf("%d : Inside main function\n",i);
    sleep(1);  // Delay for 1 second
}
return 0;
}

In the screenshot of the output of Example1.c, the program is run using time command, so that we can get an overview of the execution time of the program. We observed that in main function we call alarm() function, scheduled for 2 seconds. So, for loop is executing, after 2 seconds sig_handler function is called and the execution of main function is paused. After execution of sig_handler function, in main function for loop execution is resumed. Here we use sleep function for delaying so that we can understand the flow of the execution. The for loop is an infinite loop, when we press an interrupt key (Ctrl+C), the execution will stop.

 

Generating SIGALRM using signal() function cannot be stacked. Only one SIGALRM generation can be scheduled. Successive calls of signal() function reset the alarm clock of the calling process.

Example2.c :

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
 
void sig_handler(int signum){
 
  printf("Inside handler function\n");
}
 
int main(){
 
  signal(SIGALRM,sig_handler); // Register signal handler
 
  alarm(4);  // Scheduled alarm after 4 seconds
  alarm(1);  // Scheduled alarm after 1 seconds
 
  for(int i=1;;i++){
 
    printf("%d : Inside main function\n",i);
    sleep(1);  // Delay for 1 second
}
 
return 0;
}

In the screenshot of the output of Example2.c, we can see that the program executed more than 7 seconds but the first alarm which was scheduled after 4 second is not calling the handler function. The second alarm which was scheduled after 1 second is reset the alarm.

If the value of the argument seconds is zero, then any previously made alarm request is cancelled.

Example3.c:

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
 
void sig_handler(int signum){
 
  printf("Inside handler function\n");
}
 
int main(){
 
  signal(SIGALRM,sig_handler); // Register signal handler
 
  alarm(2);  // Scheduled alarm after 2 seconds
  alarm(0);  // Cancelled the previous alarm
 
  for(int i=1;;i++){
 
    printf("%d : Inside main function\n",i);
    sleep(1);  // Delay for 1 second
  }
 
return 0;
}

In the screenshot of the output of Example3.c, we can see that the first alarm which was scheduled after 2 seconds is cancelled because of the second alarm for 0 second.

In Example4.c we will see how continuously we can set an alarm for every 2 seconds.

Example4.c:

 

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
 
void sig_handler(int signum){
 
  printf("Inside handler function\n");
 
  alarm(2);  // Schedule a new alarm after 2 seconds
}
 
int main(){
 
  signal(SIGALRM,sig_handler); // Register signal handler
 
  alarm(2);  // Schedule the first alarm after 2 seconds
 
  for(int i=1;;i++){
 
    printf("%d : Inside main function\n",i);
    pause(); // waiting until signal is handled
}
 
return 0;
}

In the screenshot of the output of Example4.c, we can see that the alarm is continuous in every 2 seconds. We reset the alarm in the sig_handler function.

In Example5.c we will see how we can delay the alarm already scheduled. We will use SIGINT signal for interrupt. When user type Ctrl+C in keyboard, SIGINT signal will generate.

Example5.c:

 

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
 
void sig_handler(int signum){
 
  if(signum == SIGALRM){         //signal handler for SIGALRM
 
    printf("Inside handler function for SIGALRM\n");
    alarm(2);
  }
  if(signum == SIGINT){         // signal handler for SIGINT
    printf("\nSnoozing for 5 seconds....\n");
    alarm(5);
  }
 
}
 
int main(){
 
  signal(SIGALRM,sig_handler); // Register signal handler for SIGALRM
  signal(SIGINT,sig_handler); // Register signal handler for SIGINT
 
  alarm(2);  // Schedule the first alarm after 2 seconds
 
  for(int i=1;;i++){
 
    printf("%d : Inside main function\n",i);
    pause(); // waiting until signal is handled
  }
 
return 0;
}

In the screenshot of the output of Example5.c, we can see that when user type Ctrl+C the alarm is reset 5 seconds. In this program we have used only one handler function for two different signals but in the handler function it has been checked that for which signal the handler function is being called.

Conclusion:

So, we have seen that how alarm function can be set for triggering signal, how to reset alarm, how to cancel already scheduled alarm.

About the author

Bamdeb Ghosh

Bamdeb Ghosh

Bamdeb Ghosh is having hands-on experience in Wireless networking domain.He's an expert in Wireshark capture analysis on Wireless or Wired Networking along with knowledge of Android, Bluetooth, Linux commands and python. Follow his site: wifisharks.com