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);
Related
I want to implement a robust timer for an embedded linux application. The goal of this is to control over functions's time of execution and if they take too long, generate an interruption to stop the function's loop.
I searched all over the internet and the firs proposition was to use clock() function.
The solution with clock() function could be :
#include <time.h>
int func(void){
//the starting time of the function
clock_t initial_time;
clock_t elapsed_time;
initial_time = clock()*1000/CLOCKS_PER_SEC;
do{
//some stuff
elapsed_time = clock()*1000/CLOCKS_PER_SEC - initial_time;
}while(elapsed_time < timeout_ms);
printf("time to get command : %ld\n", elapsed_time);
//send an error if a timeout was reached
if(elapsed_time >= timeout_ms){
return -1;
}
else{
return 1;
}
}
But this is not really robust as clock() could cause an overflow in between the function calculations and so, elapsed time will go negative and it will never get out of the loop. This was corrected in the edit section bellow
Second solution was to use the linux kernel timers as following :
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/timer.h>
int g_time_interval = 10000;
struct timer_list g_timer;
void timer_handler (unsigned long data)
{
// do your timer stuff here
}
int init_timer(void)
{
setup_timer(&g_timer, timer_handler, 0);
mod_timer( &g_timer, jiffies + msecs_to_jiffies(g_time_interval));
return 0;
}
void close_timer(void)
{
del_timer(&g_timer);
}
This option seems ok, but I did some research and jiffies (the number of ticks since startup) could overflow too and I don't know if this could affect my usage of this timer. This was corrected in the edit section bellow
Finally, the last option I found was to use timer_create with a signal. As far as I know, this does not has the overflow issue if used with CLOCK_MONOTONIC :
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <stdbool.h>
#define SIG SIG_RTMIN
int init_timer((void *) handler(int, siginfo_t, void*)){
// Establish handler for timer signal
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIG, &sa, NULL) == -1)
printf("Error initializing timer\n");
// Block timer signal temporarily
printf("Blocking signal %d\n", SIG);
sigemptyset(&mask);
sigaddset(&mask, SIG);
// Create the timer
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
}
static void handler(int sig, siginfo_t *si, void *uc)
{
//put a flag to 1 for example
signal(sig, SIG_IGN);
}
//Much other stuff ...
But google told me that we can only set one handler per signal and I dont know if the other processus that are in my linux board use SIG_RTMIN. And as I do not want to break everything by redefining its handler, it is not a convinient solution.
Am I getting something wrong here?
Is there a way to define a timer in linux without having this issues?
Thank you very much to all :)
Edit
Overflow will not cause an issue so option 1 and 2 are valid. Now which one would be the most robust?
Here is the explanation on why I was wrong about overflow. Giving the case where we want to calculate elapsed_time and the maximum clock value is MAX. We have as above :
elapsed_time = clock()*1000/CLOCKS_PER_SEC - initial_time;
Lets rename clock()*1000/CLOCKS_PER_SEC as x. If there is overflow, then theorically theoric_x > MAX, but as there was overflow, x = theoric_x - MAX (hope is clear ':D). So :
elapsed_time = (theoric_x - MAX) - initial_time;
Which can be written as :
elapsed_time = (theoric_x - initial_time) - MAX;
And this is equivalent to : elapsed_time = (theoric_x - initial_time) because substracting the maximum value is like getting back to the same value (it works like modulo). This is ok while the theoric_x is below initial_time + MAX, if we get over, the elapsed time will reset.
I hope it was clear enough.
But google told me that we can only set one handler per signal and I dont know if the other processus that are in my linux board use SIG_RTMIN.
No, it is one handler per signal per process.
That is, having a signal handler for SIGRTMIN in your own program will not interfere with SIGRTMIN handlers of any other processes. Similarly, creating a timer will not affect any other processes' timers either. All you need to worry about, is your own process.
(Technically, there are only a limited number of timers available, so you don't want to create hundreds of them in a single process.)
If you have only one thread in the process, consider the following timeout scheme:
// SPDX-License-Identifier: CC0-1.0
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#define TIMEOUT_SIGNAL (SIGRTMIN+0)
#define TIMEOUT_REPEAT_NS 1000000 /* Repeat every millisecond until canceled */
static volatile sig_atomic_t timeout_elapsed; /* Nonzero if timeout has elapsed */
static timer_t timeout_timer;
static void timeout_handler(int signum)
{
(void)signum; /* Silences warning about unused parameter; generates no code. */
timeout_elapsed = 1;
}
static int timeout_init(void)
{
struct sigaction act;
struct sigevent evt;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = timeout_handler;
act.sa_flags = 0;
if (sigaction(TIMEOUT_SIGNAL, &act, NULL) == -1)
return errno;
memset(&evt, 0, sizeof evt);
evt.sigev_notify = SIGEV_SIGNAL;
evt.sigev_signo = TIMEOUT_SIGNAL;
evt.sigev_value.sival_ptr = (void *)0;
if (timer_create(CLOCK_BOOTTIME, &evt, &timeout_timer) == -1)
return errno;
timeout_elapsed = 0;
return 0;
}
static void timeout_cancel(void)
{
struct itimerspec zero;
zero.it_value.tv_sec = 0;
zero.it_value.tv_nsec = 0;
zero.it_interval.tv_sec = 0;
zero.it_interval.tv_nsec = 0;
timer_settime(timeout_timer, 0, &zero, NULL);
}
static void timeout_set(double seconds)
{
struct itimerspec when;
sigset_t mask;
/* Block the timeout signal for now. */
sigemptyset(&mask);
sigaddset(&mask, TIMEOUT_SIGNAL);
sigprocmask(SIG_BLOCK, &mask, NULL);
/* Make sure any previous timeouts have been canceled. */
timeout_cancel();
/* Calculate the next (relative) timeout. */
if (seconds >= 0.000000001) {
long sec = (long)seconds;
long nsec = (long)(1000000000.0*(seconds - (double)sec));
if (nsec < 0)
nsec = 0;
if (nsec > 999999999) {
nsec = 0;
sec++;
}
when.it_value.tv_sec = sec;
when.it_value.tv_nsec = nsec;
} else {
when.it_value.tv_sec = 0;
when.it_value.tv_nsec = 1;
}
/* Set it to repeat, so that it is not easily missed. */
when.it_interval.tv_sec = 0;
when.it_interval.tv_nsec = TIMEOUT_REPEAT_NS;
/* Update the timer. */
timer_settime(timeout_timer, 0, &when, NULL);
/* Clear the flag, and unblock the signal. */
timeout_elapsed = 0;
sigprocmask(SIG_UNBLOCK, &mask, NULL);
}
int main(void)
{
char *line_ptr = NULL;
size_t line_max = 0;
ssize_t line_len;
if (timeout_init()) {
fprintf(stderr, "Cannot set up timeouts: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
timeout_set(5.0);
printf("Please type input lines. This will timeout in five seconds.\n");
fflush(stdout);
while (!timeout_elapsed) {
line_len = getline(&line_ptr, &line_max, stdin);
if (line_len > 0) {
/* Remove trailing newlines */
line_ptr[strcspn(line_ptr, "\r\n")] = '\0';
printf("Read %zd bytes: \"%s\".\n", line_len, line_ptr);
fflush(stdout);
}
}
timeout_cancel();
free(line_ptr);
line_ptr = NULL;
line_max = 0;
printf("Done.\n");
return EXIT_SUCCESS;
}
Compile using gcc -Wall -Wextra -O2 example1.c -lrt -o example1 and run ./example1.
For a multithreaded process, the signal must be delivered to a specific thread, almost always the thread that sets the timeout in the first place. Here, I recommend a different approach: use a helper thread, a list or an array or a binary min-heap of CLOCK_REALTIME absolute times of the respective timeouts, waiting in pthread_cond_timedwait() for the next soonest timeout, or for a signal on the condition variable indicating the timeout list/array/heap has been updated.
POSIX defines clock_gettime. Linux also has extensions for it.
The functions clock_gettime() and clock_settime() retrieve and set the time of the specified clock clockid.
You can simply do the following:
#include <time.h>
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// Your code here...
clock_gettime(CLOCK_MONOTONIC, &end);
Then end.tv_nsec - start.tv_nsec will provide you nanoseconds with the resolution as specified by clock_getres. Sometimes this is just microseconds or even mere milliseconds. Make sure to check the value and adjust accordingly.
struct timespec res;
clock_getres(CLOCK_MONOTONIC, &res);
switch (res.tv_nsec) {
case 1000: // microseconds
case 10000000: // milliseconds
// cases ...
}
EDIT:
Rereading the original person's post I realize that this doesn't quite answer it. Still, I am leaving it here as it might be useful if applied to the problem. You are free to downvote this if you like as to allow actual answers to rise to the top.
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'm having trouble with creating and implementing a timer for a multithreaded program. I create 3 threads and they are supposed to wait for 1, 2, and 4 seconds, respectively. However all three threads never stop waiting and the program just sits there indefinitely.
I need 2 of my functions looked at:
CreateAndArmTimer():
-I'm not sure if I'm using sigemptyset and sigaddset correctly. I'm supposed to "Create the signal mask corresponding to the chosen signal_number in timer_signal". I basically looked at the man pages for pthread_sigmask and copied what I found there.
WaitFortimer():
-This function is what is causing my program to not finish. My threads function normally up until this point, and once they call this function they get trapped in it and never exit.
Both functions are located at the bottom of my code. I appreciate any help with this! I can't for the life of me get this to work.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <signal.h>
int threadNumber = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
#define NUM_THREADS 3
//used to store the information of each thread
typedef struct{
pthread_t threadID;
int num;
int policy;
struct sched_param param;
long startTime;
long endTime;
int signal_number;
int missed_signal_count;
int timer_Period;
sigset_t timer_signal;
timer_t timer_Id;
}ThreadInfo;
ThreadInfo myThreadInfo[NUM_THREADS];
void *ThreadRunner(void *vargp);
void CreateAndArmTimer(int unsigned period, ThreadInfo* threadInfo);
void WaitForTimer(ThreadInfo* threadInfo);
int sigwait(const sigset_t* set, int* sig);
int timer_create(clockid_t clockid, struct sigevent* sevp, timer_t* timerid);
//main function
int main(void){
sigset_t alarm_sig;
sigemptyset(&alarm_sig);
for(int i = SIGRTMIN; i <= SIGRTMAX; i++)
sigaddset(&alarm_sig, i);
pthread_sigmask(SIG_BLOCK, &alarm_sig, NULL); //*****apply the blocking*****
printf("\nrunning...\n");
int fifoPri = 60;
//create the 3 fifo threads
for(int i=0; i<NUM_THREADS; i++){
myThreadInfo[i].policy = SCHED_FIFO;
myThreadInfo[i].param.sched_priority = fifoPri++;
pthread_create(&myThreadInfo[i].threadID, NULL, ThreadRunner, &myThreadInfo[i]);
}
printf("\n\n");
sleep(1);
//tell all the threads to unlock
pthread_cond_broadcast(&cond);
//join each thread
for(int g = 0; g < NUM_THREADS; g++){
pthread_join(myThreadInfo[g].threadID, NULL);
}
return 0;
}
//the function that runs the threads
void *ThreadRunner(void *vargp){
struct tm *ts;
struct timeval tv;
size_t last;
time_t timestamp = time(NULL);
threadNumber++;
ThreadInfo* currentThread;
currentThread = (ThreadInfo*)vargp;
currentThread->num = threadNumber;
if(currentThread->num == 1){
currentThread->timer_Period = 1000000;
}
else if(currentThread->num == 2){
currentThread->timer_Period = 2000000;
}
else{
currentThread->timer_Period = 4000000;
}
//lock the thread until it's ready to be unlocked
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
//unlocking for all other threads
pthread_mutex_unlock(&mutex);
if(pthread_setschedparam(pthread_self(), currentThread->policy,(const struct sched_param *) &(currentThread->param))){
perror("pthread_setschedparam failed");
pthread_exit(NULL);
}
if(pthread_getschedparam(pthread_self(), ¤tThread->policy,(struct sched_param *) ¤tThread->param)){
perror("pthread_getschedparam failed");
pthread_exit(NULL);
}
//create and arm the timer
printf("thread#[%d] waiting for %d seconds\n", currentThread->num, (currentThread->timer_Period/1000000));
CreateAndArmTimer(currentThread->timer_Period, currentThread);
//set the start time of the timer
gettimeofday(&tv, NULL);
long startTime = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
currentThread->startTime = startTime;
//Wait for the timer
WaitForTimer(currentThread);
//set the end time of the timer
gettimeofday(&tv, NULL);
long endTime = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
currentThread->endTime = endTime;
//do the printing
printf("\nThread[%d] Timer Delta[%lu]us Jitter[]us\n", currentThread->num, endTime-startTime);
pthread_exit(NULL);
}
//used to create and arm a new timer
void CreateAndArmTimer(int unsigned period, ThreadInfo* threadInfo){
//Create a static int variable to keep track of the next available signal number
pthread_mutex_lock(&mutex);
static int nextSignalNumber = 0;
if(nextSignalNumber == 0){
nextSignalNumber = SIGRTMIN;
}
else{
nextSignalNumber += 1;
}
pthread_mutex_unlock(&mutex);
threadInfo->signal_number = nextSignalNumber;
//Create the signal mask corresponding to the chosen signal_number in "timer_signal"
//Use "sigemptyset" and "sigaddset" for this
sigemptyset(&threadInfo->timer_signal);
sigaddset(&threadInfo->timer_signal, SIGQUIT);
sigaddset(&threadInfo->timer_signal, SIGUSR1);
//Use timer_Create to create a timer
struct sigevent mySignalEvent;
mySignalEvent.sigev_notify = SIGEV_SIGNAL;
mySignalEvent.sigev_signo = threadInfo->signal_number;
mySignalEvent.sigev_value.sival_ptr = (void*)&(threadInfo->timer_Id);
int ret = timer_create(CLOCK_MONOTONIC, &mySignalEvent, &threadInfo->timer_Id);
if(ret != 0){
printf("error during timer_create for thread#[%d]\n", threadInfo->num);
}
//Arm timer
struct itimerspec timerSpec;
int seconds = period/1000000;
long nanoseconds = (period - (seconds * 1000000)) * 1000;
timerSpec.it_interval.tv_sec = seconds;
timerSpec.it_interval.tv_nsec = nanoseconds;
timerSpec.it_value.tv_sec = seconds;
timerSpec.it_value.tv_nsec = nanoseconds;
int ret2 = timer_settime(threadInfo->timer_Id, 0, &timerSpec, NULL);
if(ret2 != 0){
printf("error with timer_settime!\n");
}
}
//used to make a thread wait for a timer
void WaitForTimer(ThreadInfo* threadInfo){
pthread_sigmask(SIG_UNBLOCK, &threadInfo->timer_signal, NULL); //*****unblock the signal*****
//Use sigwait function to wait on the "timer_signal"
int wait = sigwait(&threadInfo->timer_signal, &threadInfo->signal_number);
if(wait != 0){
printf("error with sigwait!\n");
}
//update missed_signal_count by calling "timer_getoverrun"
threadInfo->missed_signal_count = timer_getoverrun(threadInfo->timer_Id);
}
When I run this, the output is:
running...
thread#[l] waiting for 1 seconds
thread#[2] waiting for 2 seconds
thread#[3] waiting for 4 seconds
First, you should probably be using pthread_sigmask(2) rather than sigprocmask(2). Besides the fact that your comments (instructions, if this is homework?) state that is to be used, the former is explicitly specified as part of the POSIX standard in multithreaded programs, while the latter is not. I don't think this matters on Linux, but it's probably good practice.
The second, and more important, is that you're not really using the signals correctly. First, you block every signal with the call to sigprocmask(2) in your main function, but then never change that. Inside the CreateAndArmTimer() function, you never actually specify that all signals except your threadInfo->signal_number should be blocked. You instead add SIGQUIT and SIGUSR1 to a sigset, but then never do anything with that set. Did you mean to call pthread_sigmask(2) here? If so, you should be sure to add threadInfo->signal_number to the set too before doing so.
On the "listening" side, you never actually unblock any signals in the WaitForTimer() function (or anywhere else). Even if you correctly blocked them earlier, if you don't unblock them before calling sigwait(2), they'll never be delivered to your threads. So the timer is generating the requested signals, but they're just sitting in the signal queue for your process. You must call pthread_sigmask(SIG_UNBLOCK, ...) somewhere so they can actually be delivered.
In short:
Call pthread_sigmask(2) instead of sigprocmask(2).
Block all signals except your chosen threadInfo->signal_number in the threads.
Unblock those signals before calling sigwait(2).
I have this code that I want to use to handle different signals. I don't know why it never goes to timer_handler2(). It just sticks on timer_handler(). Could someone kindly tell me what I am doing wrong
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
struct timeval theTime;
static int count = 0;
void timer_handler2(int signum) {
printf("timer 2 expired %d times\n", ++count);
}
void timer_handler(int signum) {
printf("timer 1 expired %d times\n", ++count);
}
void timer_handler3(int signum) {
printf("timer 3 expired %d times\n", ++count);
}
int main() {
struct itimerval timer, timer2, timer3, got;
signal(SIGVTALRM, timer_handler2);
signal(SIGALRM, timer_handler);
signal(SIGPROF, timer_handler3);
/* ... and every 1000 msec after that. */
timer2.it_interval.tv_sec = 1;
timer2.it_interval.tv_usec = 0;
/* Configure the timer to expire after 1000 msec... */
timer2.it_value.tv_sec = 1;
timer2.it_value.tv_usec = 0;
/* ... and every 1000 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
/* Configure the timer to expire after 1000 msec... */
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 250000;
/* ... and every 1000 msec after that. */
timer3.it_interval.tv_sec = 1;
timer3.it_interval.tv_usec = 0;
/* Configure the timer to expire after 1000 msec... */
timer3.it_value.tv_sec = 1;
timer3.it_value.tv_usec = 0;
/* Start a real timer. It counts down whenever this process is
executing. */
setitimer(ITIMER_VIRTUAL, &timer2, NULL);
setitimer(ITIMER_REAL, &timer, NULL);
setitimer(ITIMER_PROF, &timer3, NULL);
int counter = 0;
while (1) {
sleep(1);
counter++;
}
return 0;
}
How long are you letting the program run? ITIMER_VIRTUAL only decrements when the program is actually using processor time. Since your program is mostly just sleeping, it's not going to use much processor time. To verify, use the unix 'time' command (or your OS equivalent) to see the real, user and system time used by the program. I'll bet only the real time is enough to activate a timer.
You can try making your VIRTUAL and PROF timer intervals (much) smaller, or do something that doesn't block in your infinite loop (ie: remove the sleep(1) ).
I need to call a function every second exactly as I want to store the data based on the every second so I cannot miss the second? What is best method in C?
Below is a skeleton of the timer_create method is this reliable enough?
#include <stdio.h>
#include <time.h>
#include <signal.h>
timer_t gTimerid;
void start_timer(void)
{
struct itimerspec value;
value.it_value.tv_sec = 1;
value.it_value.tv_nsec = 0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_nsec = 0;
timer_create (CLOCK_REALTIME, NULL, &gTimerid);
timer_settime (gTimerid, 0, &value, NULL);
}
void stop_timer(void)
{
struct itimerspec value;
value.it_value.tv_sec = 0;
value.it_value.tv_nsec = 0;
value.it_interval.tv_sec = 0;
value.it_interval.tv_nsec = 0;
timer_settime (gTimerid, 0, &value, NULL);
}
void timer_callback(int sig)
{
printf(" Catched timer signal: %d ... !!\n", sig);
}
int main(int ac, char **av)
{
(void) signal(SIGALRM, timer_callback);
start_timer();
while(1);
}
On Linux and other POSIX systems, timer_create is the function you're looking for. Set the timer to be delivered via a signal and it will be very reliable. Don't use the older ualarm or setitimer apis which are deprecated and have various ugly issues that you probably don't want to get into unless you're already an expert on realtime unix stuff...
You have two options to call a function every other second:
Do a "busy wait"
Make your process/thread sleep for an amount of time
The first option is definitely more accurate but a lot more CPU consumptive and less responsive. It can simply be done with a while or for loop.
Here a small example of how this busy-wait loop might look like:
#include <time.h>
#define TIME_TO_WAIT 1 /* wait for one second */
...
clock_t last = clock();
while(1) {
clock_t current = clock();
if (current >= (last + TIME_TO_WAIT * CLOCKS_PER_SEC)) {
yourSpecialFunction(); /* insert your function here */
last = current;
}
}
The second option is maybe less accurate (since your process may wait a little less or more than the specified time) but it is the preferred option in terms of multiprocessing and scheduling. You can use your systems sleep()/usleep()/Sleep() (depends on your system) function for it. Alternatively you can use signals.
ualarm() is probably the simplest way of doing this. As others have mentioned, perfect accuracy isn't guaranteed, but the resolution is likely sufficient.
void each_sec(int x)
{
printf("%d", (int)time(NULL));
}
int main()
{
signal(SIGALRM, each_sec);
ualarm(1000000, 1000000);
}
I used signal for clarity, but sigaction/sigprocmask is more portable and featureful.
on Unix/Linux, you can use a timer, here's an example:
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
int limit = 10;
/* signal process */
void timeout_info(int signo)
{
if(limit == 0)
{
printf("Sorry, time limit reached.\n");
exit(0);
}
printf("only %d senconds left.\n", limit--);
}
/* init sigaction */
void init_sigaction(void)
{
struct sigaction act;
act.sa_handler = timeout_info;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGPROF, &act, NULL);
}
/* init */
void init_time(void)
{
struct itimerval val;
val.it_value.tv_sec = 1;
val.it_value.tv_usec = 0;
val.it_interval = val.it_value;
setitimer(ITIMER_PROF, &val, NULL);
}
int main(void)
{
char *str;
char c;
init_sigaction();
init_time();
printf("You have only 10 seconds for thinking.\n");
while(1);
exit(0);
}
substitute your own function for timeout_info
On Linux it is very common to use select() for timing. This way you can also be notified about file descriptors activity.
You need to have a struct timeval for interval and pass it as the last argument of select.