天天看點

POSIX timer函數 timer_creat()使用中出現的一個問題

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

繼續閱讀