天天看点

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的形式的话则可以回调成功!

继续阅读