我正在开发一个小型应用程序,在其中我希望每1秒调用一个函数。这就是我的实现方式
Timerspec.it_interval.tv_sec=1;
Timerspec.it_interval.tv_nsec=0;
Timerspec.it_value.tv_sec=1;
Timerspec.it_value.tv_nsec=0;
timer_t timerId;
struct sigaction sa;
sa.sa_handler=&TimerFn;
sa.sa_flags=0;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM,&sa,NULL);
timer_create(CLOCK_REALTIME,NULL,&timerId);
timer_settime(timerId,0,(const itimerspec*)Timerspec,NULL);
但是我想在单独的pthread中运行TimerFn函数(基本上是pthread函数的计时器)。有人可以告诉我该怎么做吗?
最佳答案
如果您可以接受每个计时器滴答创建一个新线程,则可以使用SIGEV_THREAD
:
struct sigevent evp;
memset((void *)&evp, 0, sizeof(evp));
evp.sigev_notify = SIGEV_THREAD;
evp.sigev_notify_function = &sig_alrm_handler;
evp.sigev_signo = SIGALRM;
evp.sigev_value.sigval_ptr = (void *)this;
int ret = timer_create(CLOCK_REALTIME, &evp, &_timerId);
这将为每个刻度创建一个新线程。
如果您需要在特定线程中处理信号,则需要做更多的工作:
static void *
sig_threadproc(void *thrarg)
{
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
/* endless loop to wait for and handle a signal repeatedly */
for (;;) {
int sig;
int error;
error = sigwait(&sigset, &sig);
if (error == 0) {
assert(sig == SIGALRM);
printf("got SIGALRM\n");
} else {
perror("sigwait");
}
}
return NULL;
}
static void
sig_alrm_handler(int signo)
{
/**
* dummy signal handler,
* the signal is actually handled in sig_threadproc()
**/
}
int
main(int argc, char *argv[])
{
sigset_t sigset;
struct sigaction sa;
pthread_t sig_thread;
struct itimerspec tspec;
timer_t timer_id;
/* mask SIGALRM in all threads by default */
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
sigprocmask(SIG_BLOCK, &sigset, NULL);
/* we need a signal handler.
* The default is to call abort() and
* setting SIG_IGN might cause the signal
* to not be delivered at all.
**/
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_alrm_handler;
sigaction(SIGALRM, &sa, NULL);
/* create SIGALRM looper thread */
pthread_create(&sig_thread, NULL, sig_threadproc, NULL);
/* setup timer */
tspec.it_interval.tv_sec = 1;
tspec.it_interval.tv_nsec = 0;
tspec.it_value.tv_sec = 1;
tspec.it_value.tv_nsec = 0;
timer_create(CLOCK_REALTIME, NULL, &timer_id);
timer_settime(timer_id, 0, &tspec, NULL);
/**
* this might return early if usleep() is interrupted (by a signal)
* It should not happen, since SIGALRM is blocked on the
* main thread
**/
usleep(10000000);
return 0;
}
您可能只选择在信号处理程序线程中解除对
SIGARLM
的阻塞,从而使其成为唯一有资格处理该信号的线程,但这可能无法跨系统移植。其他版本(包括使用
pthread_cond_signal()
)已在this answer中进行了讨论。关于c - 使用timer_create在单独的pthread中进行信号处理程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32283171/