I need to capture some metrics such as time to send a tcp message and number of messages sent per second in c on linux.
I am wondering if this can be done via timer, such that whenever timer expires, i simply print the metrics. The main problem is that a timer can occur while metrics are being incremented and in that case, my signal handler would print corrupt data. Is there a way to over come this issue?
So the pseudo code in my mind was to declare a global struct which would contain send time for each send and count.
struct db
{
struct sendTimes sendTimesPerSecond[10000]; // some large number which i cannot send in a second
int count;
}
where
struct sendTimes
{
timeval start_time;
timeval end_time;
}
then provide few functions that would work on struct db such as
void record_send_time(pointer_to_db, sendTimes); // simply store the times
void incrementMessagesSent(pointer_to_db); //basically count++
Then i can do something like:-
signal(SIGALRM, alarm_handler);
alarm(1)
struct db database;
for(;;) {
struct sendTimes sTime;
sTime.start_time = now(); // current time
send()
sTime.end_time = now();
record_send_time(&database, sTime);
incrementMessagesSent(&database);
}
void alarm_handler(int signo)
{
printf database;
alarm(1);
}
UPDATE:
Wildplasser comment about pipe seems to be the safest way to handle the above issue.
You can use the alarm_handler to set a flag instead of printing from the signal handler.
int print_database_flag = 0; // global flag
// ...
record_send_time(&database, sTime);
if (print_database_flag) {
printf database;
print_database_flag = 0;
}
void alarm_handler(int signo)
{
print_database_flag = 1;
alarm(1);
}
Use getrusage(2) which has two struct timeval capturing time used up by our program in user (your code) and kernel mode (sends and the such).
#include <sys/time.h>
#include <sys/resource.h>
.
struct rusage start, end;
getrusage(RUSAGE_SELF, &start);
// do what you have to do
getrusage(RUSAGE_SELF, &end);
struct timeval utime, stime;
timersub(&end.ru_utime, &start.ru_utime, &utime);
timersub(&end.ru_stime, &start.ru_stime, &stime);
printf("Work took %lu microseconds of user time and %lu microseconds of system time\n",
(utime.tv_sec * 1000 * 1000) + utime.tv_usec,
(stime.tv_sec * 1000 * 1000) + stime.tv_usec
);
Related
We use posix interval timer (created using timer_create()) in our process that generates SIGALRM on timer expiration. The generated signal is handled asynchronously (sigwait) by a specific thread in the process and we have blocked the signal in all other threads using sig_block. ‘Sig_block’ is invoked in the main thread before the child threads are spawned and so child threads inherit it from parent (i.e., main). However this comes with a caveat that if any of the libraries included in the process spawn any thread during dllmain, the signal will not get blocked in that thread. Also we don't have control over the internal implementation of the DLLs that we include in the process. Can you suggest how to handle this problem? Is there any other way to target the timer expiration signal to specific thread in the process?
I checked the option 'SIGEV_THREAD_ID'. However the documentation states that it is intended only for use by threading libraries.
If you do not mind being Linux-specific, use SIGEV_THREAD_ID. Also, I recommend using a realtime signal (SIGRTMIN+0 through SIGRTMAX-0, inclusive), since these are queued and delivered in the order they were sent.
The reason SIGEV_THREAD_ID is documented as intended for use only by threading libraries is that Linux thread IDs are not normally exposed; this interface is not directly usable with e.g. pthreads. You will need to implement your own gettid():
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
static inline pid_t gettid(void) { return syscall(SYS_gettid); }
That will rely on Linux pthreads not doing anything silly, like switching thread-ids while keeping the same pthread_t ID.
Personally, I suggest a different approach, using a helper thread to maintain the timeouts.
Have a thread maintain a sorted array or a binary heap of timeout timestamps, associated with the target thread ID (pthread_t). The thread will wait in pthread_cond_timedwait() until next timeout expires, or it is signaled, indicating that the timeouts have changed (cancelled or new ones added). When one or more timeouts expire, the thread uses pthread_sigqueue() to send the appropriate signal to the target thread, with the timeout identifier as a payload.
Perhaps a rough simplified sketch helps understand. For simplicity, let's say the pending timeouts form a singly linked list:
struct timeout {
struct timeout *next;
struct timespec when; /* Absolute CLOCK_REALTIME time */
double repeat; /* Refire time in seconds, 0 if single-shot */
pthread_id thread;
int elapsed;
};
pthread_mutex_t timeout_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t timeout_wait = PTHREAD_COND_INITIALIZER;
struct timeout *timeout_pending = NULL;
int timeout_quit = 0;
static inline int timespec_cmp(const struct timespec t1, const struct timespec t2)
{
return (t1.tv_sec < t2.tv_sec) ? -1 :
(t1.tv_sec > t2.tv_sec) ? +1 :
(t1.tv_nsec < t2.tv_nsec) ? -1 :
(t1.tv_nsec > t2.tv_nsec) ? +1 : 0;
}
static inline void timespec_add(struct timespec *const ts, const double seconds)
{
if (seconds > 0.0) {
ts->tv_sec += (long)seconds;
ts->tv_nsec += (long)(1000000000.0*(double)(seconds - (long)seconds));
if (ts->tv_nsec < 0)
ts->tv_nsec = 0;
if (ts->tv_nsec >= 1000000000) {
ts->tv_sec += ts->tv_nsec / 1000000000;
ts->tv_nsec = ts->tv_nsec % 1000000000;
}
}
}
struct timeout *timeout_arm(double seconds, double repeat)
{
struct timeout *mark;
mark = malloc(sizeof (timeout));
if (!mark) {
errno = ENOMEM;
return NULL;
}
mark->thread = pthread_self();
mark->elapsed = 0;
clock_gettime(CLOCK_REALTIME, &(mark->when));
timespec_add(&(mark->when), seconds);
mark->repeat = repeat;
pthread_mutex_lock(&timeout_lock);
mark->next = timeout_pending;
timeout_pending = mark;
pthread_cond_signal(&timeout_wait);
pthread_mutex_unlock(&timeout_lock);
return mark;
A call to timeout_arm() returns a pointer to the timeout as an identifier, so that the thread can disarm it later:
int timeout_disarm(struct timeout *mark)
{
int result = -1;
pthread_mutex_lock(&timeout_lock);
if (timeout_pending == mark) {
timeout_pending = mark->next;
mark->next = NULL;
result = mark->elapsed;
} else {
struct timeout *list = timeout_pending;
for (; list->next != NULL; list = list->next) {
if (list->next == mark) {
list->next = mark->next;
mark->next = NULL;
result = mark->elapsed;
break;
}
}
}
/* if (result != -1) free(mark); */
pthread_mutex_unlock(&timeout_lock);
return result;
}
Note that the above function does not free() the timeout structure (unless you uncomment the line near the end), and it returns -1 if the timeout cannot be found, and the elapsed field at the time when the timeout was removed if successful.
The thread function managing the timeouts is rather simple:
void *timeout_worker(void *unused)
{
struct timespec when, now;
struct timeout *list;
pthread_mutex_lock(&timeout_lock);
while (!timeout_quit) {
clock_gettime(CLOCK_REALTIME, &now);
/* Let's limit sleeps to, say, one minute in length. */
when = now;
when.tv_sec += 60;
/* Act upon all elapsed timeouts. */
for (list = timeout_pending; list != NULL; list = list->next) {
if (timespec_cmp(now, list->when) >= 0) {
if (!list->elapsed || list->repeat > 0) {
const union sigval value = { .sival_ptr = list };
list->elapsed++;
pthread_sigqueue(list->thread, TIMEOUT_SIGNAL, value);
timespec_add(&(list->when), list->repeat);
}
} else
if (timespec_cmp(when, list->when) < 0) {
when = list->when;
}
}
pthread_cond_timedwait(&timeout_wait, &timeout_lock, &when);
}
/* TODO: Clean up timeouts_pending list. */
return NULL;
}
Note that I haven't checked the above for typos, so there might be some. All code above is licensed under CC0-1.0: do whatever you want, just don't blame me for any errors.
Unfortunately, the behavior you’d like, directing a timer’s signal to a specific thread, is not portable.
To work around your DLL’s naïve behavior — so naïve I’d consider it buggy — you have a few portable options.
You could invoke your program with SIGALRM already blocked, before you exec.
Your timer could specify SIGEV_THREAD instead, and then that thread could either handle the timeout or inform your dedicated thread that it’s time to work.
You could implement the time keeping yourself, without signals, in a synchronously sleeping thread, as Glärbo suggests.
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.
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 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.