多线程下的多定时器处理

来源:互联网 发布:江苏省软件协会地址 编辑:程序博客网 时间:2024/05/17 17:18

原文地址:http://hi.baidu.com/sunwater007/blog/item/5f9d71accfa3900f4b36d6d9.html

 问题的提出:多线程中每个线程都需要一个单独的定时器,而且其他线程并不知道该线程中的定时器的存在,由于普通的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
ctrl+^

原创粉丝点击