linux 用户空间周期定时器C语言使用demo 使用多线程实现定时器效率对比 及一个问题记录

本文探讨了一个程序中为何出现非预期的定时间隔,通过实例展示了C/C++中信号处理与多线程定时器的运行情况。作者深入剖析了setitimer在ITIMER_REAL模式下的行为,并对比了与多线程实现的效率。
摘要由CSDN通过智能技术生成
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>

void signalHandler(int signo)
{
	static int i = 0;
	static struct timeval tvNew ={0,0};
	static struct timeval tvOld ={0,0};
    switch (signo){
        case SIGALRM:
			if(tvOld.tv_sec != 0)
            {
				gettimeofday(&tvNew,NULL);
				printf("i is %d time is %ld\n", i%25, (tvNew.tv_sec - tvOld.tv_sec)*1000*1000 + tvNew.tv_usec - tvOld.tv_usec);
				tvOld = tvNew;
			}
			else
			{
				gettimeofday(&tvOld,NULL);
				
			}
			usleep((i %25) * 100000);
			//if(i % 2 == 0) 
			//    sleep(2);	
			i++;
            break;
   }
}

int main(int argc, char *argv[])
{
    signal(SIGALRM, signalHandler);

    struct itimerval new_value, old_value;
    new_value.it_value.tv_sec = 1;//执行完setitimer后过多少秒进入第一个SIGALRM信号处理
    new_value.it_value.tv_usec = 0;//执行完setitimer后过多少微秒进入SIGALRM第一个信号处理,第一个参数的小数,本例中表示1s后进入第一个SIGALRM信号处理
    new_value.it_interval.tv_sec = 1;//开始执行第一个SIGALRM信号处理后周期进入SIGALRM信号处理的周期秒
    new_value.it_interval.tv_usec = 0;//开始执行第一个SIGALRM信号处理后周期进入SIGALRM信号处理的周期微秒,本demo表示定时周期为1s
    setitimer(ITIMER_REAL, &new_value, &old_value);
    //system("date");
    for(;;);
     
    return 0;
}

典型demo如上,执行结果如下:

i is 1 time is 999992
i is 2 time is 1000003
i is 3 time is 1000000
i is 4 time is 1000011
i is 5 time is 999982
i is 6 time is 1000000
i is 7 time is 1000001
i is 8 time is 1000002
i is 9 time is 999997
i is 10 time is 999997
i is 11 time is 1000071
i is 12 time is 1100136
i is 13 time is 1200107
i is 14 time is 1300159
i is 15 time is 1400149
i is 16 time is 1500147
i is 17 time is 1600191
i is 18 time is 1700155
i is 19 time is 1800142
i is 20 time is 1900158
i is 21 time is 2000131
i is 22 time is 2100134
i is 23 time is 2200131
i is 24 time is 2300165
i is 0 time is 2400144
i is 1 time is 497905
i is 2 time is 999983
i is 3 time is 999996
i is 4 time is 1000002
i is 5 time is 999998
i is 6 time is 999999
i is 7 time is 1000004
i is 8 time is 1000005
i is 9 time is 999989
i is 10 time is 999997
i is 11 time is 1000078
i is 12 time is 1100179
........

有一个问题就是为啥存在i is 1 time is 497905 这个打印,而不是间隔一秒左右?记录下,以后撸下系统源码看看,如果各位有高见也可解答下

接下来看下linux定时器与多线程实现定时器的效率对比,测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <pthread.h>

void signalHandler(int signo)
{
	static int i = 0;
	static struct timeval tvNew ={0,0};
	static struct timeval tvOld ={0,0};
    switch (signo){
        case SIGALRM:
			if(tvOld.tv_sec != 0)
            {
				gettimeofday(&tvNew,NULL);
				printf("i is %d time is %ld\n", i%25, (tvNew.tv_sec - tvOld.tv_sec)*1000*1000 + tvNew.tv_usec - tvOld.tv_usec);
				tvOld = tvNew;
			}
			else
			{
				gettimeofday(&tvOld,NULL);
				
			}
			//usleep((i %25) * 100000);
			//if(i % 2 == 0) 
			//    sleep(2);	
			i++;
            break;
   }
}

void *producter(void *arg)
{
	static int i = 0;
	static struct timeval tvNew ={0,0};
	static struct timeval tvOld ={0,0};
	
	while(1)
	{
		if(tvOld.tv_sec != 0)
            {
				gettimeofday(&tvNew,NULL);
				printf("i is %d time is %ld\n", i%25, (tvNew.tv_sec - tvOld.tv_sec)*1000*1000 + tvNew.tv_usec - tvOld.tv_usec);
				tvOld = tvNew;
			}
			else
			{
				gettimeofday(&tvOld,NULL);
				
			}
			sleep(1);
	}

}

int main(int argc, char *argv[])
{
	#if 1
    signal(SIGALRM, signalHandler);

    struct itimerval new_value, old_value;
    new_value.it_value.tv_sec = 1;//执行完setitimer后过多少秒进入第一个SIGALRM信号处理
    new_value.it_value.tv_usec = 0;//执行完setitimer后过多少微秒进入SIGALRM第一个信号处理,第一个参数的小数,本例中表示1s后进入第一个SIGALRM信号处理
    new_value.it_interval.tv_sec = 1;//开始执行第一个SIGALRM信号处理后周期进入SIGALRM信号处理的周期秒
    new_value.it_interval.tv_usec = 0;//开始执行第一个SIGALRM信号处理后周期进入SIGALRM信号处理的周期微秒,本demo表示定时周期为1s
    setitimer(ITIMER_REAL, &new_value, &old_value);
    //system("date");
	#else
		pthread_t ptid;
		pthread_create(&ptid, NULL, producter, NULL);
		pthread_join(ptid, NULL);
	#endif
    for(;;)
		sleep(10);
     
    return 0;
}

使用linux库定时器时的资源占用:

使用多线程时的资源占用:

 

一目了然! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值