一)ANSI clock函数
vi test1.c
3)总结:
timeval结型体的原型如下:
测试:
1)精确度比较:
以下是各种精确度的类型转换:
1秒=1000毫秒(ms), 1毫秒=1/1000秒(s);
1秒=1000000 微秒(μs), 1微秒=1/1000000秒(s);
1秒=1000000000 纳秒(ns),1纳秒=1/1000000000秒(s);
2)
clock()函数的精确度是10毫秒(ms)
times()函数的精确度是10毫秒(ms)
gettimofday()函数的精确度是微秒(μs)
clock_gettime()函数的计量单位为十亿分之一,也就是纳秒(ns)
3)测试4种函数的精确度:
vi test4.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/times.h>
#include <sys/time.h>
#define WAIT for(i=0;i<298765432;i++);
#define MILLION 1000000
int
main ( int argc, char *argv[] )
{
int i;
long ttt;
clock_t s,e;
struct tms aaa;
/* use clock() function */
s=clock();
WAIT;
e=clock();
printf("clock time : %.12f/n",(e-s)/(double)CLOCKS_PER_SEC);
/* use times() function */
long tps = sysconf(_SC_CLK_TCK);
s=times(&aaa);
WAIT;
e=times(&aaa);
printf("times time : %.12f/n",(e-s)/(double)tps);
/* use gettimeofday() function */
struct timeval tvs,tve;
gettimeofday(&tvs,NULL);
WAIT;
gettimeofday(&tve,NULL);
double span = tve.tv_sec-tvs.tv_sec + (tve.tv_usec-tvs.tv_usec)/1000000.0;
printf("gettimeofday time: %.12f/n",span);
/* use clock_gettime() function */
struct timespec tpstart;
struct timespec tpend;
clock_gettime(CLOCK_REALTIME, &tpstart);
WAIT;
clock_gettime(CLOCK_REALTIME, &tpend);
double timedif = (tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec)/1000000000.0;
printf("clock_gettime time: %.12f/n", timedif);
return EXIT_SUCCESS;
}
gcc -lrt test4.c -o test4
debian:/tmp# ./test4
clock time : 1.190000000000
times time : 1.180000000000
gettimeofday time: 1.186477000000
clock_gettime time: 1.179271718000
六)内核时钟
默认的Linux时钟周期是100HZ,而现在最新的内核时钟周期默认为250HZ.
如何得到内核的时钟周期呢?
grep ^CONFIG_HZ /boot/config-2.6.26-1-xen-amd64
CONFIG_HZ_250=y
CONFIG_HZ=250
结果就是250HZ.
而用sysconf(_SC_CLK_TCK);得到的却是100HZ
例如:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/times.h>
#include <sys/time.h>
int
main ( int argc, char *argv[] )
{
long tps = sysconf(_SC_CLK_TCK);
printf("%ld/n", tps);
return EXIT_SUCCESS;
}
为什么得到的是不同的值呢?
因为sysconf(_SC_CLK_TCK)和CONFIG_HZ所代表的意义是不同的.
sysconf(_SC_CLK_TCK)是GNU标准库的clock_t频率.
它的定义位置在:/usr/include/asm/param.h
例如:
#ifndef HZ
#define HZ 100
#endif
最后总结一下内核时间:
内核的标准时间是jiffy,一个jiffy就是一个内部时钟周期,而内部时钟周期是由250HZ的频率所产生中的,也就是一个时钟滴答,间隔时间是4毫秒(ms).
也就是说:
1个jiffy=1个内部时钟周期=250HZ=1个时钟滴答=4毫秒
每经过一个时钟滴答就会调用一次时钟中断处理程序,处理程序用jiffy来累计时钟滴答数,每发生一次时钟中断就增1.
而每个中断之后,系统通过调度程序跟据时间片选择是否要进程继续运行,或让进程进入就绪状态.
最后需要说明的是每个操作系统的时钟滴答频率都是不一样的,LINUX可以选择(100,250,1000)HZ,而DOS的频率是55HZ.
七)为应用程序计时
用time程序可以监视任何命令或脚本占用CPU的情况.
1)bash内置命令time
例如:
time sleep 1
real 0m1.016s
user 0m0.000s
sys 0m0.004s
2)/usr/bin/time的一般命令行
例如:
/time sleep 1
0.00user 0.00system 0:01.01elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1major+176minor)pagefaults 0swaps
注:
在命令前加上斜杠可以绕过内部命令.
/usr/bin/time还可以加上-v看到更具体的输出:
/time -v sleep 1
Command being timed: "sleep 1"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 0%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.00
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 0
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 178
Voluntary context switches: 2
Involuntary context switches: 0
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
这里的输出更多来源于结构体rusage.
最后,我们看到real time大于user time和sys time的总和,这说明进程不是在系统调用中阻塞,就是得不到运行的机会.
而sleep()的运用,也说明了这一点.