我正在开发一个小型应用程序,在其中我希望每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/

10-11 09:27
查看更多