Linux 计时器 函数

来源:互联网 发布:自制印章软件 编辑:程序博客网 时间:2024/06/14 13:01

转载地址:http://blog.csdn.net/whz_zb/article/details/6938442


程序注册三个定时器,分别对实际时间、进程使用CPU时间、用户使用CPU时间进行即时,计时时间为10秒。同时设定一个用户信号,当该信号在用户指定的空计次循环后到来。在用户信号到来后,打印各个计时器走过的时间值,并计算出内核所用的时间。到实际时间计时器到达10秒后产生定时器信号时,程序打印各计时器走过的时间,并退出程序。

因为需要获得定时器的时间,因此,我们需要使用setitimer和getitimer计时器。使用这两个计时器要频繁的对itimerval和timeval这两个结构体进行操作。首先,应该对这两个结构体在本实例中常用到的操作进行封装。封装的函数包括,timeval的比较,计算两个timeval的时间差,计算itimerval走过的时间(因为itimerval记录的是定时器剩余时间)。为了显示的需要,我们需要封装一个对timeval打印的函数。

之后,我们需要设计信号和信号处理函数,这里我们一共需要两个信号:SIGALRM和SIGUSR1。因为信号处理函数有一个int型参数,该参数可以用来区分信号。考虑到,两个信号到来以后都需要进行时间计算。因此可以考虑将两个信号写成一个函数,通过参数识别,在不同的位置进行不同的处理。


[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <time.h>  
  3. #include <sys/time.h>  
  4. #include <stdlib.h>  
  5. #include <signal.h>  
  6.   
  7. /* 函数声明 */  
  8. /* 信号处理函数 */  
  9. static void SigHandler(int signo);  
  10.   
  11. /* 操作辅助函数 */  
  12. void TimerPassed(const struct itimerval *itimer, struct timeval *tv);  
  13. void TimeSubstract(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tvres);  
  14. int TimeCompare(const struct timeval *tv1, const struct timeval *tv2);  
  15. void PrintTimeval(const char *str, const struct timeval *tv);  
  16.   
  17. /* 主函数,程序入口点 */  
  18. int main()  
  19. {  
  20.     /* 变量声明 */  
  21.     struct itimerval myitimer;  
  22.     long i, count;  
  23.   
  24.     /* 注册信号处理函数 */  
  25.     /* 注册用户信号1处理函数 */  
  26.     if (signal(SIGUSR1, SigHandler) == SIG_ERR) {  
  27.         printf("Unable to create handler for SIGUSR1\n");  
  28.         exit(0);  
  29.     }  
  30.     /* 定时器信号处理函数 */  
  31.     /* 这里将同一个函数注册给两个信号,函数内部存在区分信号类型的逻辑 */  
  32.     if (signal(SIGALRM, SigHandler) == SIG_ERR){  
  33.         printf("Unable to create handler for SIGALRM\n");  
  34.         exit(0);  
  35.     }  
  36.   
  37.     /* 运行参数输入 */  
  38.     printf("Loop times between timer info outputs (300 Recommanded):\n");  
  39.     scanf("%ld", &count);  
  40.     count *= 1000000;  
  41.   
  42.     /* 初始化定时器参数 */  
  43.     myitimer.it_interval.tv_sec = 10;  
  44.     myitimer.it_interval.tv_usec = 0;  
  45.     myitimer.it_value.tv_sec = 10;  
  46.     myitimer.it_value.tv_usec = 0;  
  47.   
  48.     /* 注册定时器 */  
  49.     setitimer(ITIMER_REAL, &myitimer, NULL);     /* 实时定时器 */  
  50.     setitimer(ITIMER_VIRTUAL, &myitimer, NULL); /* 用户定时器 */  
  51.     setitimer(ITIMER_PROF, &myitimer, NULL);     /* CPU定时器 */  
  52.   
  53.     /* 无限循环,等待信号处理 */  
  54.     while (1)  
  55.     {  
  56.         for (i=0; i < count; i++);  
  57.         /* 每进行指定次数的循环后,发送用户信号1给自己 */  
  58.         raise(SIGUSR1);  
  59.     }  
  60. }  
  61.   
  62.   
  63.   
  64. /* 信号处理函数 */  
  65. static void SigHandler(int signo)  
  66. {  
  67.     /* 变量声明 */  
  68.     struct itimerval tmp_itimer;  
  69.     struct timeval realtv, cputv, usertv, kerneltv;  
  70.       
  71.     /* 获得实时定时器时间 */  
  72.     getitimer(ITIMER_REAL, &tmp_itimer);  
  73.     TimerPassed(&tmp_itimer, &realtv);  
  74.       
  75.     /* 获得CPU定时器时间 */  
  76.     getitimer(ITIMER_PROF, &tmp_itimer);  
  77.     TimerPassed(&tmp_itimer, &cputv);  
  78.   
  79.     /* 获得用户定时器时间 */  
  80.     getitimer(ITIMER_VIRTUAL,&tmp_itimer);  
  81.     TimerPassed(&tmp_itimer, &usertv);  
  82.   
  83.     /* 计算Linux内核使用CPU时间 */  
  84.     TimeSubstract(&cputv, &usertv, &kerneltv);  
  85.   
  86.     /* 按照信号进行处理 */  
  87.     switch (signo)  
  88.     {  
  89.     /* 用户信号1 */  
  90.     case SIGUSR1:  
  91.         /* 输出各种时间值 */  
  92.         PrintTimeval("Real Time ", &realtv);  
  93.   
  94.         PrintTimeval("CPU Time   ", &cputv);  
  95.   
  96.         PrintTimeval("User Time ", &usertv);  
  97.   
  98.         PrintTimeval("Kernel Time", &kerneltv);  
  99.   
  100.         printf("\n");  
  101.   
  102.         break;  
  103.   
  104.     /* 定时器信号 */  
  105.     case SIGALRM:  
  106.         /* 输出时间值后退出程序 */  
  107.         printf("Time up, the application will escape.\n");  
  108.   
  109.         PrintTimeval("CPU Time   ", &cputv);  
  110.   
  111.         PrintTimeval("User Time ", &usertv);  
  112.   
  113.         PrintTimeval("Kernel Time", &kerneltv);  
  114.   
  115.         exit(0);  
  116.         break;  
  117.     }  
  118. }  
  119.   
  120.   
  121. /* 计算时间的流逝 */  
  122.   
  123. void TimerPassed(const struct itimerval *itimer, struct timeval *tv)  
  124.   
  125. {  
  126.     TimeSubstract(&(itimer->it_interval), &(itimer->it_value), tv);  
  127. }  
  128.   
  129.   
  130. /* 计算两个时间的差值 */  
  131. void TimeSubstract(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tvres)  
  132. {  
  133.     /* 变量声明 */  
  134.     const struct timeval *tmptv1, *tmptv2;  
  135.     int cmpres;  
  136.       
  137.     /* 比较tv1和tv2,将较大值赋给tmptv1,较小值赋给tmptv2 */  
  138.     cmpres = TimeCompare(tv1, tv2);  
  139.     if (cmpres > 0) {  
  140.         tmptv1 = tv1;  
  141.         tmptv2 = tv2;  
  142.     }   
  143.     else {  
  144.         tmptv1 = tv2;  
  145.         tmptv2 = tv1;    
  146.     }  
  147.   
  148.     /* 做差时存在借位的情况 */  
  149.     if (tmptv1->tv_usec < tmptv2->tv_usec) {  
  150.         /* 结果的秒数多减1,借给微秒 */  
  151.         tvres->tv_sec = tmptv1->tv_sec - tmptv2->tv_sec - 1;  
  152.         /* 微秒做减法时,先加上借来的一秒(1000000微秒) */  
  153.         tvres->tv_usec = tmptv1->tv_usec + 1000000 - tmptv2->tv_usec;  
  154.     /* 不存在借位的情况 */  
  155.     } else {  
  156.         /* 对应的秒和微秒分别做差 */  
  157.         tvres->tv_sec = tmptv1->tv_sec - tmptv2->tv_sec;  
  158.         tvres->tv_usec = tmptv1->tv_usec - tmptv2->tv_usec;  
  159.     }  
  160. }  
  161.   
  162. /* 时间值比较大小 */  
  163. int TimeCompare(const struct timeval *tv1, const struct timeval *tv2)  
  164. {  
  165.     /* 如果秒值不一致则秒值大者较大 */  
  166.     if (tv1->tv_sec > tv2->tv_sec)  
  167.         return 1;  
  168.     else if (tv1->tv_sec < tv2->tv_sec)  
  169.         return -1;  
  170.     /* 秒值相同的,微秒值较大者较大 */  
  171.     else if (tv1->tv_usec > tv2->tv_usec)  
  172.         return 1;  
  173.     else if (tv1->tv_usec < tv2->tv_usec)  
  174.         return -1;  
  175.     /* 秒值和微秒值皆相同者等值 */  
  176.     else  
  177.         return 0;  
  178. }  
  179.   
  180.   
  181. /* 打印时间 */  
  182.   
  183. void PrintTimeval(const char *str, const struct timeval *tv)  
  184. {  
  185.     printf("%s = %ld sec %ld usec\n", str, tv->tv_sec, tv->tv_usec);  
  186. }  

程序会提示你输入空循环的次数,2.7GHz的CPU在空闲的时候使用300至500时大约会1秒钟显示一次时间。数值越大显示时间的间隔越长,根据你的计算机的具体情况而定。此外输出的数据也各你当前系统状态而定。


0 0