I want to trigger a timer each second for 30 seconds. However, the timer is triggered only once and the program stops. How to make the timer run for 30 seconds?
#include <sys/time.h>
#include <signal.h>
void alarmhandler(){
printf("\nTimer triggered");
}
void main(){
struct itimerval timerval;
signal(SIGALRM, alarmhandler);
timerval.it_value.tv_sec = 1;
timerval.it_value.tv_usec = 0;
timerval.it_interval.tv_sec = 30;
timerval.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &timerval, 0);
pause();
}
After receiving a signal your program gets unpaused and it just goes to the end of main() and returns. You need to pause it again, of you want to wait for another signal.
One problem you have is the first timer trigger ends the pause call and your program terminates. The pause command is described like this:
The pause function suspends program execution until a signal arrives whose action is either to execute a handler function, or to terminate the process.
Another problem is that you're using the "interval" incorrectly. That value is supposed to be the number that the timer is reset to if it is a repeating timer. So to trigger every second, you need to set it to 1.
Now, if you want it to run for 30 seconds, you'll need to maintain a counter, and then reset the timer after that counter is finished. Finally, you need to keep re-pausing until enough interrupts have been serviced.
Try this:
#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
volatile int timer_remain = 30;
void alarmhandler()
{
static struct itimerval notimer = { 0 };
printf( "Timer triggered\n" );
if( --timer_remain == 0 )
{
setitimer( ITIMER_REAL, ¬imer, 0 );
}
}
int main()
{
struct itimerval timerval = { 0 };
timerval.it_value.tv_sec = 1;
timerval.it_interval.tv_sec = 1;
signal( SIGALRM, alarmhandler );
setitimer( ITIMER_REAL, &timerval, 0 );
while( timer_remain > 0 )
{
pause();
}
printf( "Done\n" );
return 0;
}
One last thing to note is that there's no guarantee that the timer will be delivered every second if system load is high.
Related
This question already has answers here:
How to use timer in C?
(4 answers)
Closed 2 years ago.
I need to run a while loop in C for exactly 10 seconds. I tried this:
clock_t start = clock();
while( ( clock() - start ) < ( 10 * CLOCKS_PER_SEC ) ) {
work..
}
but it is not working.
Seems like what you may really want is an actual timer so that when a specified time interval passes a function is called. In that function you can handle disconnecting clients from the server.
See: https://programming.vip/docs/linux-c-language-timer.html
You should be able to modify this example to do as you need:
#include<stdio.h>
#include<signal.h>
#Include<sys/time.h>//itimerval structure definition
int handle_count=0;
void set_time(void)
{
struct itimerval itv;
itv.it_interval.tv_sec=10;//Load automatically and then respond every 10 seconds
itv.it_interval.tv_usec=0;
itv.it_value.tv_sec=5;//Time of First Timing
itv.it_value.tv_usec=0;
setitimer(ITIMER_REAL,&itv,NULL);
}
void alarm_handle(int sig)
{
handle_count++;
printf("have handle count is %d\n",handle_count);
}
void main(void)
{
struct itimerval itv;
signal(SIGALRM,alarm_handle);
set_time();
while(1){
getitimer(ITIMER_REAL,&itv);
printf("pass second is %d\n",(int)itv.it_value.tv_sec);
sleep(1);
}
return;
}
Some man page links:
https://linux.die.net/man/2/getitimer
https://linux.die.net/man/2/alarm
Another example from another StackOverflow answer:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
static unsigned int pass_value_by_pointer = 42;
void Timer_has_expired(union sigval timer_data)
{
printf("Timer expiration handler function; %d\n", *(int *) timer_data.sival_ptr);
}
int main(void)
{
struct sigevent timer_signal_event;
timer_t timer;
struct itimerspec timer_period;
printf("Create timer\n");
timer_signal_event.sigev_notify = SIGEV_THREAD;
timer_signal_event.sigev_notify_function = Timer_has_expired; // This function will be called when timer expires
// Note that the following is a union. Assign one or the other (preferably by pointer)
//timer_signal_event.sigev_value.sival_int = 38; // This argument will be passed to the function
timer_signal_event.sigev_value.sival_ptr = (void *) &pass_value_by_pointer; // as will this (both in a structure)
timer_signal_event.sigev_notify_attributes = NULL;
timer_create(CLOCK_MONOTONIC, &timer_signal_event, &timer);
printf("Start timer\n");
timer_period.it_value.tv_sec = 1; // 1 second timer
timer_period.it_value.tv_nsec = 0; // no nano-seconds
timer_period.it_interval.tv_sec = 0; // non-repeating timer
timer_period.it_interval.tv_nsec = 0;
timer_settime(timer, 0, &timer_period, NULL);
sleep(2);
printf("----------------------------\n");
printf("Start timer a second time\n");
timer_settime(timer, 0, &timer_period, NULL);
sleep(2);
printf("----------------------------\n");
printf("Start timer a third time\n");
timer_settime(timer, 0, &timer_period, NULL);
printf("Cancel timer\n");
timer_delete(timer);
sleep(2);
printf("The timer expiration handler function should not have been called\n");
return EXIT_SUCCESS;
}
Please specify what is not working. I'm gonna guess:
On Debian 10 the correct macro is CLOCKS_PER_SEC. But maybe Ubuntu added CLOCKS_PER_SECOND as an alias, in which case that is not the problem you have.
The way you implemented your timer, you may loop further than 10 seconds (if your "work" time is not a divisor of 10s).
If that is your actual issue, you should check asynchronous tasks and signals.
This way you can have one process (or thread) making your initial work in a infinite loop, and a second process notifying the first one (eg. with a signal) after 10 seconds elapsed. But that will require a much more complex code!
I hope I brought you some help, but if I did not try to be more precise in your question.
I am trying to implement a timer that continuously counts certain amount of time while the software is running. I wrote a dirty code to try how sys/time.h works.
My understanding is that if I set my it_interval struct to a non-zero value, then the timer should start counting again once it's done counting for the value stored in it_value struct.
However, my code stalls. Could someone tell me what I am missing in my code please? Also, I am using Linux.
#include <sys/time.h>
#include <stdio.h>
#include <stdint.h>
int main(void) {
struct itimerval timer1;
timer1.it_interval.tv_sec = 5;
timer1.it_interval.tv_usec = 0;
timer1.it_value.tv_sec = 5;
timer1.it_value.tv_usec = 0 ;
setitimer(ITIMER_REAL, &timer1, NULL);
printf( "init interval counter: %ld.%ld\n", timer1.it_interval.tv_sec,
timer1.it_interval.tv_usec);
printf( "init value counter: %ld.%ld\n\n", timer1.it_value.tv_sec,
timer1.it_value.tv_usec );
while(1) {
for (int i = 0; i < 100000000000000; i++){
getitimer(ITIMER_REAL, &timer1);
printf( "end interval counter: %ld.%ld\n",
timer1.it_interval.tv_sec, timer1.it_interval.tv_usec);
printf( "end value counter: %ld.%ld\n\n",
timer1.it_value.tv_sec, timer1.it_value.tv_usec );
}
}
return 0;
}
My output (shortened of course) is:
end interval counter: 5.0
end value counter: 0.8821
end interval counter: 5.0Alarm clock
Process returned 142 (0x8E) execution time: 5.033 s
Thank you in advance for your help!
setitimer(ITIMER_REAL,...) causes SIGALRM to be sent to the calling process upon timer expiry. SIGALRM is a normally deadly signal, whose default disposition is to kill the process.
If you want to prevent your process from being killed by this signal, you need to handle it somehow.
Example (prints EXPIRED from the handler every 100ms) based on your code:
#include <sys/time.h>
#include <stdio.h>
#include <stdint.h>
#include <signal.h>
#include <unistd.h>
void handler(int Sig)
{
(void)Sig;
char msg[]="EXPIRED\n";
ssize_t nwr = write(1,msg,sizeof(msg)-1); (void)nwr;
}
int main(void) {
struct itimerval timer1;
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM,&sa,0);
timer1.it_interval.tv_sec = 0;
timer1.it_interval.tv_usec = 100000;
timer1.it_value.tv_sec = 0;
timer1.it_value.tv_usec = 100000 ;
setitimer(ITIMER_REAL, &timer1, NULL);
printf( "init interval counter: %ld.%ld\n", timer1.it_interval.tv_sec,
timer1.it_interval.tv_usec);
printf( "init value counter: %ld.%ld\n\n", timer1.it_value.tv_sec,
timer1.it_value.tv_usec );
while(1) pause();
return 0;
}
The program should print to the screen every 5 seconds and state "alive at %d milliseconds\n". When the user types in <Control><A> for the polling program or <Control><C> for the interrupt version, the program should stop and output:
program terminated by user. Total time is %d milliseconds %d seconds\n.
My Program:
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
volatile sig_atomic_t print_flag = false;
void handle_alarm( int sig ) {
print_flag = true;
}
int main() {
struct timeval start, stop;
double secs = 0;
char key_press;
char input_key;
int ascii_value;
float time_taken;
clock_t t;
t = clock();
gettimeofday(&start, NULL);
signal( SIGALRM, handle_alarm );
alarm( 5 );
for (;;) {
if ( print_flag ) {
print_flag = false;
alarm( 5 );
gettimeofday(&stop, NULL);
secs = (double)(stop.tv_usec - start.tv_usec) / 1000000 + (double)(stop.tv_sec - start.tv_sec) * 1000;
printf("Alive at %f ms \n",secs);
input_key=getchar();
ascii_value=input_key;
if(ascii_value==1) {
t = clock() - t;
time_taken = ((float)t)/CLOCKS_PER_SEC; // in seconds
printf("total time taken= %f sec", time_taken);
break;
}
}
}
}
I want the program to run continuously but when I press ctrl a it should terminate. The program prints "Alive at 5000.000 ms and stops printing. The program prints infinitely every 5 seconds if I don't add the code for terminating using ctrl A. How to make it work?
When you ask for input in this way, you are using synchronous blocking I/O. The process hangs until input is given. If you wish for your program to continue functioning while waiting for input you need to delve into asynchronous non-blocking I/O. Look up the select() function
https://en.wikipedia.org/wiki/Asynchronous_I/O
https://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html
After you do print_flag = false; in the for loop, you never set print_flag back to true again. Hence, the code in the if ( print_flag ) block is executed only once.
How to make it work?
To make it work, you need to set print_flag to true before you check whether it is true.
We want to add a timer to our C program under Linux platform.
We are trying to send the packets and we want to find out how many packets get sent in 1 minute. We want the timer to run at the same time as the while loop for sending the packet is being executed. For example:
while(1)
{
send packets;
}
This loop will keep on sending the packets until ctrl-z is pressed. The timer should be used to stop the loop after 60 seconds.
You could do something like this:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
volatile int stop=0;
void sigalrm_handler( int sig )
{
stop = 1;
}
int main(int argc, char **argv)
{
struct sigaction sact;
int num_sent = 0;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
sact.sa_handler = sigalrm_handler;
sigaction(SIGALRM, &sact, NULL);
alarm(60); /* Request SIGALRM in 60 seconds */
while (!stop) {
send_a_packet();
num_sent++;
}
printf("sent %d packets\n", num_sent);
exit(0);
}
If loop overhead turns out to be excessive, you could amortize the overhead by sending N packets per iteration and incrementing the count by N each iteration.
Just check the time on every iteration of the loop and when 1 minute has elapsed, count how many packets you have sent.
Edit changed to reflect what the question actually asks!
time_t startTime = time(); // return current time in seconds
int numPackets = 0;
while (time() - startTime < 60)
{
send packet
numPackets++;
}
printf("Sent %d packets\n", numPackets);
Can also check this http://www.gnu.org/software/libc/manual/html_node/Setting-an-Alarm.html to set timers which will send signals to your process and you can stop the while loop.
Look at the standard time() function.
Here is code snippet of itimer that can be used for different time intervals on C with linux platform:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 1 sec... */
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
/* ... and every 1000 msec after that. */
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
/* Start a virtual timer. It counts down whenever this process is
* executing. */
setitimer (ITIMER_VIRTUAL, &timer, NULL);
/* Do busy work. */
while (1);
sleep(1);
}
hope it will help.
Use wheetimer (and its variant) data structures to implement timers.
man 3 sleep:
NAME
sleep - Sleep for the specified number of seconds
SYNOPSIS
#include < unistd.h >
unsigned int sleep(unsigned int seconds);
I want to create a timer in our C program so that it can print the variable after every 1 second.
Can anybody help me in doing this?
Don't use busy waiting, because you've got 100% CPU utilization.
You must use system function which turns process into sleeping mode for example select():
#include <stdio.h>
#include <sys/select.h>
void your_callback()
{
printf("%s\n", __FUNCTION__);
}
int main()
{
struct timeval t;
while (1) {
t.tv_sec = 1;
t.tv_usec = 0;
select(0, NULL, NULL, NULL, &t);
your_callback();
}
return 0;
}
If all you are interested in doing is printing the value of a variable at a one second interval, using time(2) or clock(3) as suggested in the other answers might suffice. In general, I would not recommend these busy-waiting techniques.
If your program is more complex, I suggest you investigate using the alarm(2) or settimer(2) function to asynchronously deliver a signal to your application at a one second interval.
The following example uses select(2) to block indefinitely in order to minimize CPU usage associated with busy-waiting techniques. The blocking select() call is interrupted and returns when a signal is caught. In the case of the SIGALRM signal, the print_variable flag is set and the value of variable is printed.
Example 1: using alarm()
#include <signal.h>
#include <stdio.h>
#include <sys/select.h>
#include <unistd.h>
volatile unsigned int variable = 0;
volatile unsigned int print_variable = 0;
void alarm_handler(int signum)
{
variable++;
print_variable = 1;
alarm(1);
}
int main()
{
signal(SIGALRM, alarm_handler);
alarm(1);
for (;;)
{
select(0, NULL, NULL, NULL, NULL);
if (print_variable)
{
printf("Variable = %u\n", variable);
}
}
}
Note: Error checking was omitted from the above code for simplicity.
A printf() function could have been called inside the SIGALRM handler, but calling non-reentrant functions in a signal handler is generally discouraged.
A timeout of one second can also be passed to select(), but if it were interrupted by any signal, additional logic is necessary to ensure that the remainder of the one second timeout is honored. Fortunately on Linux, select() modifies the timeout value to reflect the amount of time not slept. This allows interruption cases to be detected followed by subsequent call(s) select() to complete the timeout.
Example 2: using select()
#include <errno.h>
#include <stdio.h>
#include <sys/select.h>
volatile unsigned int variable = 0;
int main()
{
struct timeval tv;
int val;
for (;;)
{
tv.tv_sec = 1;
tv.tv_usec = 0;
do
{
val = select(0, NULL, NULL, NULL, &tv);
} while (val != 0 && errno == EINTR);
printf("Variable = %u\n", ++variable);
}
}
If you want only second precision. Use time(0) which returns current time if time.h is included.
update:
Adding simple example which prints 10 in every second during 20 seconds:
#include <time.h>
#include <stdio.h>
int main()
{
int a = 10;
int num = 20;
int c = time(0);
while(n--)
{
printf("%d\n", a);
while(!(time(0) - c));
c = time(0);
}
return 0;
}
use time(0) see this example
/* timer.c */
#include <stdio.h>
#include <time.h>
void delay_sec( int seconds ){
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC;
while (clock() < endwait) {}
}
int main (void){
time_t rawtime, ini_time, now;
struct tm *ptm;
time ( &ini_time );
for(;;){
time ( &rawtime );
//ptm = gmtime ( &rawtime );
//printf ("%2d:%02d:%02d\n", ptm_2->tm_hour, ptm_2->tm_min, ptm_2->tm_sec);
now = rawtime - ini_time;
ptm = gmtime ( &now );
printf ("%2d:%02d:%02d\n", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
delay_sec(1);
}
return 0;
}
I believe you know 1000 Milliseconds equals to 1 Second.
#include <stdio.h>
#include <time.h>
#define mydelay 1000
void delay(int mseconds)
{
clock_t wait = mseconds + clock();
while (wait > clock());
}
int main()
{
int i=100;
while(1)
{
printf("%d\n",i);
delay(mydelay);
}
return 0;
}
A simple example which prints the value of the variable a for every 1 sec:
#include<stdio.h>
void main(void)
{
int a = 10;
while(a--)
{
printf("Value of a = %d\n", a);
sleep(1);
}
}
Output:
Value of a = 9
...
value of a = 0