Linux 定时器和信号问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5740954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Problem in Timers and signal
提问by kingsmasher1
I have implemented a POSIX timer using timer_create( ) API, and this will generate SIGUSR1 when the timer expires for which i have put a handler code. Now the problem is, if this program receives another SIGUSR1, then the same signal handler will be invoked and caught.
我已经使用 timer_create() API 实现了一个 POSIX 计时器,这将在计时器到期时生成 SIGUSR1,我已经为其放置了处理程序代码。现在的问题是,如果这个程序接收到另一个 SIGUSR1,那么将调用并捕获相同的信号处理程序。
Is there any way to prevent this, so that the handler can catch signals only generated by the timer?
有什么方法可以防止这种情况发生,以便处理程序可以捕获仅由计时器生成的信号?
采纳答案by Rumple Stiltskin
Will this work for you? (Modified the code from example in timer_create
man page.)
这对你有用吗?(修改了timer_create
手册页示例中的代码。)
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;
static void handler(int sig, siginfo_t *si, void *uc)
{
if(si->si_value.sival_ptr != &timerid){
printf("Stray signal\n");
} else {
printf("Caught signal %d from timer\n", sig);
}
}
int main(int argc, char *argv[])
{
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs;
sigset_t mask;
struct sigaction sa;
printf("Establishing handler for signal %d\n", SIG);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIG, &sa, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCKID, &sev, &timerid);
/* Start the timer */
its.it_value.tv_sec = 10;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
timer_settime(timerid, 0, &its, NULL);
sleep(100);
exit(EXIT_SUCCESS);
}
When signal from timer is caught Caught signal 10 from timer
will be displayed. Otherwise Stray signal
will be displayed.
当来自定时器的信号被捕获时Caught signal 10 from timer
将显示。否则Stray signal
会显示。
回答by Patryk
The question is whether you really need to use signals. You may think of using callback that will be called when the timer expires:
问题是你是否真的需要使用信号。您可能会想到使用将在计时器到期时调用的回调:
void cbf(union sigval);
struct sigevent sev;
timer_t timer;
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = cbf; //this function will be called when timer expires
sev.sigev_value.sival_ptr = (void*) arg;//this argument will be passed to cbf
timer_create(CLOCK_MONOTONIC, &sev, &timer);
The callback function will be called in a new thread.
回调函数将在新线程中调用。
回答by Milan
No, there is no easy way. Why don't you use SIGUSR2 instead for your timers if you have something else generating SIGUSR1 together with your timer. If that is not enough, use one of the real time signals for your application.
不,没有简单的方法。如果您有其他东西与您的计时器一起生成 SIGUSR1,为什么不使用 SIGUSR2 代替您的计时器。如果这还不够,请为您的应用程序使用一种实时信号。
If it must be able to handle the same signal from the timer and some other source, then depending on how fast, how many, what system, etc etc you could try setting a timestamp before registering a timer on when the timer will approximately exit, and then in the signal handler try to deduce if it was within time margin. I would strongly advise not to use this approach, but instead redesign what you are doing.
如果它必须能够处理来自计时器和其他一些来源的相同信号,那么根据多快、多少、什么系统等,您可以尝试在注册计时器之前设置时间戳,以确定计时器大约何时退出,然后在信号处理程序中尝试推断它是否在时间裕度内。我强烈建议不要使用这种方法,而是重新设计你正在做的事情。
回答by Yann Droneaud
Use another RT signals. See answers on Is there any way to create a user defined signal in Linux?
使用另一个 RT 信号。请参阅有没有办法在 Linux 中创建用户定义的信号?