Since you have tagged your question with embedded-linux
I assume that portability is not an issue. In that case you might want to have a look at timerfd. It will allow you to use select(2)
/poll(2)
to receive your timer events. It will also make it easier to combine the interval timer with other event sources such as file descriptors.
How to implement a timed loop?
-
18-07-2023 - |
题
I need to execute some code 1000 times per second. I would like to do something like:
set up interval timer
while (1)
{
wait for timer
do something
}
My attempt looks like
// Create timer
timer_t timerid;
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
if (timer_create(CLOCK_REALTIME, &sev, &timerid))
{
perror("timer_create");
exit(1);
}
// Every one mSec (10^6 nsec)
struct itimerspec its;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 1000000;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 1000000;
if (timer_settime(timerid, 0, &its, NULL))
{
perror("timer_settime");
exit(1);
}
// Create mask to wait for SIGUSR1
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
while (1)
{
int sig;
// Wait for the timer: Do this loop once per millisecond
sigwait(&set, &sig);
(do something)
}
When I try this, I just get "User defined signal 1" at the console and my program exits. This is not surprising, as this is the default action for the signal. If I set the signal to SIG_IGN using sigaction(2), I never get to my (do something).
I presume I need to do something with sigaction(2), but I don't see an option for "deliver the signal". I don't want to ignore the signal, or do the default action, or call a function. What's the best way to accomplish my goal?
Or I can just give up and put my (do something) in a function :-)
Edit: I implemented the timerfd idea, and it seems to be working. On to the next bug...
解决方案
其他提示
I think you should set a true signal handler as suggested by n.m. Look at man sigaction
for your version of Linux. You can either call your do_something
in signal handler (and wait for something else for program termination) or have a return only handler and keep you sigwait logic.