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的形式的話則可以回調成功!