Linux下应用开发可利用的计时器技术2:CPU时钟滴答

来源:互联网 发布:网络数字用语 编辑:程序博客网 时间:2024/05/02 18:43

      在Linux的内核时钟驱动中,当PIT通道0的计数器减到0时,就在IRQ0中产生一次时钟中断,也即一次时钟滴答。Linux用宏HZ来表示时钟滴答的频率。且在不同的平台上HZ有不同的定义值。对于ALPHA和IA62平台HZ的值是1024,对于SPARC、MIPS、ARM和i386等平台HZ的值都是100。

      该宏在i386平台上的定义如下(include/asm-i386/param.h):
      #ifndef HZ
      #define HZ 100
      #endif
     

      通过以上了解到,在i386平台下,1秒种产生100次时钟滴答。那么,如果我们知道从系统启动起到当前时刻的时钟滴答数,那也就能计算出当前时刻相对于系统启动时间的相对时间了。进而可以设计出应用程序自己的定时器。

      现在剩余的问题就是,我们如何获知从系统启动到当前时刻共经历了多少时间滴答呢?幸运的是,/proc/stat中的统计数据提供了我们想要的数据。/proc/stat中包含了一些内核和系统的统计信息,该数据都是自系统启动以来的各项指标的总计。

      例如

> cat /proc/stat
  cpu  2255 34 2290 22625563 6290 127 456 0 0
  cpu0 1132 34 1441 11311718 3675 127 438 0 0
  cpu1 1123 0 849 11313845 2614 0 18 0 0

 

      其中cpu行展示了自系统启动以来,cpu执行所有各项不同操作分别消耗的时钟滴答数。"CPU[n]"代表的是第n个cpu,"CPU"行是所有CPU的累积数据。没行各有9列,分别是:

      user:从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies),不包含 nice值为负进程。1jiffies=0.01秒=一个时间滴答

      nice:从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
      system:从系统启动开始累计到当前时刻,内核态所执行时间

      idle:从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间

      iowait:从系统启动开始累计到当前时刻,硬盘IO等待时间

      irq:从系统启动开始累计到当前时刻,硬中断时间

      softirq:从系统启动开始累计到当前时刻,软中断时间

      steal:involuntary wait

      guest:running a guest

 

      有了以上理论基础后,就可以开始计算当前时间相对于系统启动时间经过过多少秒了。

      step1  获取时钟滴答频率:

                 frequence = sysconf(_SC_CLK_TCK)

      step2  计算当前时间:读取虚文件/proc/stat,获取CPU统计数据,则

                 time = (user+nice+system+idle+iowait+irq+softirq+steal+guest)/frequence


 

      本方法存在的问题:

      1、计算时间时,需经历读取时钟频率,读虚文件/proc/stat(虽然该文件时常驻内存的),解析/proc/stat文件中的CPU行字符,对

           统计数据进行数学运算。这都需要消耗一定的时间,那么应用程序拿到的这个时间有一定的精度误差.

      2、(未解的疑问)既然/proc/stat只是一个虚文件,那么必然存在文件中数据更新的问题。如果文件更新频率大于时钟滴答频率,则不

           会有问题,而若小于时钟滴答频率的话,就会又增加一个误差值了。

      因此,如果对时钟有高精度要求,建议使用RTC时钟方法。若要求不高的话,使用CPU时钟滴答计数法,也勉强能行。

 

      注意点:

      1、若多线程并发读取/proc/stat虚文件进行时钟计算,可能会使CPU利用率达到80%,甚至100%

 

      参考:./filesystems/proc.txt

 

原创粉丝点击