POSIX提供了以下接口来设置定时器:
int timer_create(clockid_t which_clock, struct sigevent* timer_event_spec, timer_t* created_timer_id);
int timer_gettime(timer_t timer_id, struct itimerspec* setting);
int timer_settime(timer_t timer_id, int flags, struct itimerspec* new_setting, struct itimerspec* old_setting);
int timer_delete(timer_t timer_id);
而以下函数在运行时出现了预料之外的现象(test_rate是传进来的定时器时间长度,test_on是static volatile sig_atomic_t 类型,初始化为1):
int test_dejitter(unsigned int test_rate)
{
struct sigevent event;
timer_t timer_id;
struct itimerspec value;
struct itimerspec get_time;
int ret = -1;
/
unsigned int traup_len,bts_id,cxn;
/
printf("test time interval is %ds \n",test_rate);
event.sigev_notify = SIGEV_THREAD;
event.sigev_notify_function=timer_cb;
value.it_interval.tv_sec = 0;
value.it_interval.tv_nsec = 0;
value.it_value.tv_sec = test_rate;
value.it_value.tv_nsec = 0;
ret = timer_create(CLOCK_REALTIME,&event,&timer_id);
printf("timer_create() returns %d\n",ret);
printf("Start to test! \n");
gettimeofday(&tv1, NULL);
ret = timer_settime(timer_id, 0, &value, NULL);
printf("timer_settime() returns %d\n",ret);
while(test_on){
bts_id = rand()%NBBTS;
cxn = rand()%NBCONNECTONS;
rtp_parsing_sim(cxn,&dl_rtp[0],0,btss[bts_id].pos,&traup_len);
printf("In loop after rtp_parsing_sim(), test_on = %d! \n",test_on);
timer_gettime(timer_id,&get_time);
printf("\033[33mtimer_gettime() returns:interval.tv_sec = %d, \
interval.tv_nsec = %d, it_value.tv_sec = %d, \
it_value.tv_nsec = %d \033[0m\n",\
get_time.it_interval.tv_sec,\
get_time.it_interval.tv_nsec,\
get_time.it_value.tv_sec,\
get_time.it_value.tv_nsec);
sleep(1);
}
gettimeofday(&tv2, NULL);
printf("\033[35mTest ended at %fs ! \033[0m\n",\
tv2.tv_sec - tv1.tv_sec + (tv2.tv_usec - tv1.tv_usec)/1000000.0);
return 1;
}
其中,第28行的函数和定时器和test_on都没有任何关系的一段处理函数。
运行该函数,传进的test_rate值为3时,结果为:
test time interval is 3s
timer_create() returns 0
Start to test!
timer_settime() returns 0
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 2, it_value.tv_nsec = 999966476
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 1, it_value.tv_nsec = 999153244
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 0, it_value.tv_nsec = 998183847
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 0, it_value.tv_nsec = 0
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 0, it_value.tv_nsec = 0
定时器没有响应回调函数!!
而如果注释掉第28行代码,不运行该函数的话定时器回调成功!
而将第13行,定时器的event通知方式改为:
event.sigev_notify = SIGEV_SIGNAL; //SIGEV_THREAD;//
event.sigev_signo = SIGALRM;
并添加信号处理函数:
signal(SIGALRM,timer_cb);
得到的结果为:
test time interval is 3s
timer_create() returns 0
Start to test!
timer_settime() returns 0
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 2, it_value.tv_nsec = 999965638
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 1, it_value.tv_nsec = 998988977
In loop after rtp_parsing_sim(), test_on = 1!
timer_gettime() returns:interval.tv_sec = 0, interval.tv_nsec = 0, it_value.tv_sec = 0, it_value.tv_nsec = 998036342
time call back
teston is set to 0, test is going to stop after 3.001004s !
Test ended at 3.001125s !
定时器回调成功!
分析初步原因是 通过SIGEV_THREAD方式的定时器响应通知方式创建线程来收集信号,通过ps -elfm可以看到进程创建了线程,而定时器响应时主线程没有响应,初步判断线程没有得到执行! 可能和结构体SIGEVENT中sigev_notify_attributes成员的设置有关,详细见manpage,(http://www.chineselinuxuniversity.net/man-pages/man7/sigevent.7.html)
而换用signal的形式的话则可以回调成功!