目录
1 进程时间概念
2 times 函数
2.1 times 函数介绍
2.2 示例程序
3 clock 函数
3.1 clock 函数介绍
3.2 示例程序
1 进程时间概念
进程时间指的是进程从创建后(也就是程序运行后)到目前为止这段时间内使用 CPU 资源的时间总数,出于记录的目的,内核把 CPU 时间(进程时间) 分为以下两个部分:
- 用户 CPU 时间:进程在用户空间(用户态)下运行所花费的 CPU 时间。有时也成为虚拟时间(virtual time)。
- 系统 CPU 时间:进程在内核空间(内核态)下运行所花费的 CPU 时间。这是内核执行系统调用或代表进程执行的其它任务(譬如,服务页错误)所花费的时间。
一般来说,进程时间指的是用户 CPU 时间和系统 CPU 时间的总和,也就是总的 CPU 时间
Tips:进程时间不等于程序的整个生命周期所消耗的时间, 如果进程一直处于休眠状态(进程被挂起、不会得到系统调度),那么它并不会使用 CPU 资源,所以休眠的这段时间并不计算在进程时间中。
2 times 函数
2.1 times 函数介绍
times
函数是用来获取进程占用CPU的时间信息的,函数返回自进程启动以来,在用户模式和内核模式下消耗的CPU时间。times
函数的原型定义在sys/times.h
头文件中,其定义如下:
#include <sys/times.h>
clock_t times(struct tms *buf);
- buf:times()会将当前进程时间信息存在一个 struct tms 结构体数据中,其定义如下:
struct tms {
clock_t tms_utime; // 用户模式下的CPU时间
clock_t tms_stime; // 内核模式下的CPU时间
clock_t tms_cutime; // 子进程在用户模式下的CPU时间
clock_t tms_cstime; // 子进程在内核模式下的CPU时间
};
返回值: 返回值类型为 clock_t(实质是 long 类型), 调用成功情况下,将返回从过去任意的一个时间点(譬如系统启动时间) 所经过的时钟滴答数(其实就是系统节拍数), 将(节拍数 / 节拍率)便可得到秒数,返回值可能会超过 clock_t 所能表示的范围(溢出); 调用失败返回-1,并设置 errno。
2.2 示例程序
下面的程序通过 times()来计算程序中某一段代码执行所耗费的进程时间和总的时间,测试程序如下所示:
#include <stdio.h>
#include <sys/times.h>
#include <unistd.h>
#include <time.h>
int main() {
struct timespec start, end;
clock_t start_clk_t, end_clk_t;
struct tms start_tms, end_tms;
long clock_ticks;
int i;
// 获取系统时钟的滴答数
clock_ticks = sysconf(_SC_CLK_TCK);
// 记录开始时间(CPU时间和实际时间)
times(&start_tms);
clock_gettime(CLOCK_MONOTONIC, &start);
// 模拟一些工作,例如循环
for (i = 0; i < 1000000; i++) {
// 这里可以放置一些计算操作,比如 i * i
}
// 记录结束时间(CPU时间和实际时间)
times(&end_tms);
clock_gettime(CLOCK_MONOTONIC, &end);
// 计算CPU时间差(用户模式和内核模式)
clock_t total_utime = end_tms.tms_utime - start_tms.tms_utime;
clock_t total_stime = end_tms.tms_stime - start_tms.tms_stime;
// 计算实际运行时间差(秒和纳秒)
long seconds = end.tv_sec - start.tv_sec;
long nanoseconds = end.tv_nsec - start.tv_nsec;
// 打印结果
printf("User mode CPU time used: %ld seconds\n", total_utime / clock_ticks);
printf("Kernel mode CPU time used: %ld seconds\n", total_stime / clock_ticks);
printf("Real time used: %ld seconds and %ld nanoseconds\n", seconds, nanoseconds);
return 0;
}
程序中使用 sysconf(_SC_CLK_TCK)获取到系统节拍率,程序还使用了一个库函数 sleep()模拟程序运行,可以看到用户 CPU 时间为 1.9 秒,系统 CPU 时间为 0 秒,也就是说测试的这段代码并没有进入内核态运行,所以总的进程时间 = 用户 CPU 时间 + 系统 CPU 时间 = 1.9 秒。运行结果如下:
3 clock 函数
3.1 clock 函数介绍
clock
函数是用来获取程序的CPU时间(也就是进程时间)。函数返回自程序启动以来,程序所占用的CPU时间总量,包括用户模式和内核模式下的时间。clock
函数的原型定义在time.h
头文件中,其定义如下:
#include <time.h>
clock_t clock(void);
注意:clock()函数虽然可以很方便的获取总的进程时间,但并不能获取到单独的用户 CPU 时间和系统 CPU 时间,在实际编程当中,根据自己的需要选择。
3.2 示例程序
下面是一个使用clock
函数的简单示例:
#include <stdio.h>
#include <time.h>
int main() {
clock_t start, end;
double cpu_time_used;
int i, j;
start = clock(); // 记录开始时间
for (i = 0; i < 20000; i++)
for (j = 0; j < 20000; j++)
; // 空操作,用于消耗CPU时间
end = clock(); // 记录结束时间
// 计算CPU时间使用量(秒)
cpu_time_used = (double)(end - start) / CLOCKS_PER_SEC;
printf("CPU time used: %f seconds\n", cpu_time_used);
return 0;
}
程序首先记录了程序开始时的CPU时间,然后执行了一些操作,接着记录了结束时的CPU时间。通过计算这两个时间的差值,我们得到了程序占用CPU的总时间,并将其转换为秒。程序运行结果如下: