多线程下的多定时器处理

多线程下的多定时器处理

  问题的提出:多线程中每个线程都需要一个单独的定时器,而且其他线程并不知道该线程中的定时器的存在,由于普通的unix处理定时器的信号方式是一个进程下只能有一个定时器起作用。如果设置多个定时器可能被后续的定时器洗刷掉。那么如何让多个线程独立的使用不同的信号而不被洗刷掉呢?

  问题的解决:由于目前的posix里面定义了SIGMIN~SIGMAX信号供用户自定义以扩展程序,那么最好采用此类信号,而不是用32之前的信号;同时使用sigaction代替signal函数,避免信号丢失的问题; 定时器采用posix TMR方案,不能使用普通的itimer结构。

综上所述,实现的代码如下:

/***********************************************************/

* Because some platforms define different names for signals between SIGMIN and SIGMAX or other

* similar ones. you may use "kill -l" to get these self-defined signals in your platform.

* Compile:gcc -lrt -lpthread test.c -o test

* Run:     ./test

* By kinghuang, gdnt rnd.

* sunwater007@gmail.com

*/

#include   <stdio.h>

#include   <time.h>

#include   <signal.h>

void timer1_handler(int signo)

{

    static int index = 0;

    printf("timer1_handler captures signal: %d, index: %d\n", signo, index++);

}

void timer2_handler(int signo)

{

    static int index = 0;

    printf("timer2_handler, sig: %d, index: %d\n", signo, index++);

}

void set_timer1()

{

    struct sigaction     sig_act;

    struct sigevent      sig_event;

    sigset_t                sig_set;

    struct itimerspec   timer_setting;

    timer_t                 timer_id;

    // set sigaction.

    sigemptyset(&sig_act.sa_mask);

    sig_act.sa_flags = 0;

    sig_act.sa_handler = timer1_handler;

    if ( sigaction(SIGRTMIN + 2, &sig_act, NULL) < 0)

    {   printf(" timer1 sigaction meets problem.\n"); return; }

    sig_event.sigev_notify = SIGEV_SIGNAL;

    sig_event.sigev_signo = SIGRTMIN + 2;

    if ( timer_create(CLOCK_REALTIME, &sig_event, &timer_id) < 0)

    {   printf("create timer1 failed.\n"); return; }

    timer_setting.it_value.tv_sec = 1;

    timer_setting.it_value.tv_nsec = 0;

    timer_setting.it_interval.tv_sec = 1;

    timer_setting.it_interval.tv_nsec = 0;

    if ( timer_settime(timer_id, 0, &timer_setting, NULL) < 0)

    {   printf("set timer failed. \n"); return; }

    sigemptyset(&sig_set);

    while ( 1)

    {   sigsuspend(&sig_set); }

}

void set_timer2()

{

    struct sigaction     sig_act;

    struct sigevent      sig_event;

    sigset_t                sig_set;

    struct itimerspec   timer_setting;

    timer_t                timer_id;

    // set sigaction.

    sigemptyset(&sig_act.sa_mask);

    sig_act.sa_flags = 0;

    sig_act.sa_handler = timer2_handler;

    if ( sigaction(SIGRTMAX - 1, &sig_act, NULL) < 0)

    {   printf(" timer1 sigaction meets problem.\n"); return; }

    // set signal event for the timer timeout.

    sig_event.sigev_notify = SIGEV_SIGNAL;

    sig_event.sigev_signo = SIGRTMAX - 1;

    if ( timer_create(CLOCK_REALTIME, &sig_event, &timer_id) < 0)

    {   printf("create timer1 failed.\n"); return; }

    // timer setting. The setting can be used by more than one timer.

    timer_setting.it_value.tv_sec = 1;

    timer_setting.it_value.tv_nsec = 0;

    timer_setting.it_interval.tv_sec = 1;

    timer_setting.it_interval.tv_nsec = 0;

    if ( timer_settime(timer_id, 0, &timer_setting, NULL) < 0)

    {   printf("set timer failed. \n"); return; }

    sigemptyset(&sig_set);

    // wait for timer timeout.

    while ( 1)

    {   sigsuspend(&sig_set); }

}

int main()

{

    pthread_t t1, t2;

    pthread_create(&t1, NULL, (void *)set_timer1, NULL);

    pthread_create(&t2, NULL, (void *)set_timer2, NULL);

    pthread_join(t2, NULL);

    return 0;

}

/************************************************************/

run result:

king>./test

timer2_handler, sig: 63, index: 0

timer1_handler captures signal: 36, index: 0

timer2_handler, sig: 63, index: 1

timer1_handler captures signal: 36, index: 1

timer2_handler, sig: 63, index: 2

timer1_handler captures signal: 36, index: 2

timer2_handler, sig: 63, index: 3

timer1_handler captures signal: 36, index: 3

转自:http://hi.baidu.com/sunwater007/item/aa179939f7a491c7392ffa91

posted @ 2020-09-11 14:01  陈木  阅读(765)  评论(0)    收藏  举报