1日历时间(Calendar time)

1.1简介

Calendartime 是距离某一个物理世界的时间点的时间。对于Linux来说,是距离1970年1月1日早上0点的秒数,这个时间点也被称为epoch

1.2获取日历时间

使用time函数,该函数返回一个time_t类型,这是我们需要的,而入口参数给一个NULL就不用管了

1
2
3
4
5
6
7
#include <time.h>
#include <stdio.h>
int main(){
time_t cur_time;
cur_time = time(NULL);
printf("cur_time is %ld\n",cur_time);
}

运行结果:

image-20220919020641766

1.3日历时间格式转换

通过time函数获取的只是秒数,如果想要人类方便理解的字符串的展示形式,或者将时分秒,年月日,分别储存在不同的变量中(分解时间),需要进行相应的转换。

Linux提供了一系列进行时间格式转换的函数,想要时间的各种表达格式都能找到,非常方便

image-20220919020711977
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//
// Created by liode on 2022/9/18.
//
#include <stdio.h>
#include <time.h>
int main(){
time_t cur_time;
cur_time = time(NULL);
printf("time_t by time() is\n\t%ld\n",cur_time);
//time_t -> 固定格式的字符串
char* fixed_format_string;
fixed_format_string = ctime(&cur_time);
printf("time_t to fixed_format_string by ctime() is\n\t%s",fixed_format_string);//自带一个回车一个终止字符
//time_t -> 分解时间
struct tm *broken_down_time;
broken_down_time = gmtime(&cur_time);
printf("time_t to broken-down time by gmtime() is:\n\t");
printf("year=%d mon=%d mday=%d hour=%d min=%d sec=%d ", broken_down_time->tm_year,
broken_down_time->tm_mon, broken_down_time->tm_mday, broken_down_time->tm_hour, broken_down_time->tm_min, broken_down_time->tm_sec);
printf("wday=%d yday=%d isdst=%d\n", broken_down_time->tm_wday, broken_down_time->tm_yday, broken_down_time->tm_isdst);
broken_down_time = localtime(&cur_time);
printf("time_t to broken-down time by localtime() is:\n\t");
printf("year=%d mon=%d mday=%d hour=%d min=%d sec=%d ", broken_down_time->tm_year,
broken_down_time->tm_mon, broken_down_time->tm_mday, broken_down_time->tm_hour, broken_down_time->tm_min, broken_down_time->tm_sec);
printf("wday=%d yday=%d isdst=%d\n", broken_down_time->tm_wday, broken_down_time->tm_yday, broken_down_time->tm_isdst);
//分解时间 -> time_t
time_t cur_timeby_mktime = mktime(broken_down_time);
printf("broken-time to time_t by mktime() is\n\t%ld\n",cur_timeby_mktime);
//分解时间 -> 固定格式的字符串
fixed_format_string = asctime(broken_down_time);
printf("broken-down time to fixed_format_string by astime() is\n\t%s",fixed_format_string);//自带一个回车一个终止字符
return 0;
}

Output:

image-20220919020800555

2进程时间(CPU time/Process time)

2.1简介

进程时间不是真实物理世界的绝对时间,是cpu执行指令花费的时间。有用户cpu时间和系统cpu时间两种,分别表示在cpu在用户态和内核态执行指令所花费的时间。

注意:

如果程序在执行,但是cpu没有在执行指令,进程时间也是不增长的。比如sleep函数,就是这种情况。

2.2使用命令测量进程时间

在shell可以使用time命令来查看程序消耗的cpu时间

1
2
3
4
5
	#include <unistd.h>
int main(){
sleep(5);
return 0;
}

Output

image-20220919021003790

可以看到,实际程序执行了5.01s,cpu在用户态执行指令花费了0.003s,在内核态执行指令花费了0.001s

2.3使用系统调用来测量进程时间

a使用times函数

times函数将程序自执行以来的进程时间储存在入口参数中,返回值一般不使用。

image-20220919021025327 image-20220919021103734

cputime的单位是 clock tick , 如果需要换算成秒,需要除以 sysconf(_SC_CLK_TCK)的返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	#include <stdio.h>
#include <sys/times.h>
#include <unistd.h>
int main(){
struct tms t;
times(&t);
long clk_tck = sysconf(_SC_CLK_TCK);
printf("In point a ,tms_utime is %ld , tms_stime is %ld , user cpu time is %.2f s , system cpu time is %.2f s\n",t.tms_utime,t.tms_stime,\
(double )t.tms_utime/clk_tck,(double )t.tms_stime/clk_tck);
sleep(5);
for(int i = 100000000;i>0;i--){
getpid();
}
times(&t);
printf("In point b ,tms_utime is %ld , tms_stime is %ld , user cpu time is %.2f s , system cpu time is %.2f s\n",t.tms_utime,t.tms_stime,\
(double )t.tms_utime/clk_tck,(double )t.tms_stime/clk_tck);
return 0;
}

Output:

image-20220919021153499

b使用clock函数

clock函数返回一个clock_t类型的值,如果需要转换成秒数,需要除以宏CLOCKS_PER_SEC,这两个都在<tim.h>中被声明,而且clock函数只能观察总的cpu时间,不能像times一样,分别查看内核态和用户态的cpu时间

image-20220919021219321
1
2
3
4
5
6
7
8
9
10
11
12
13
14
	#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main(){
clock_t t;
t = clock();
printf("In point a, clock_t is %ld, second is %.2f s\n",t,(double )t/CLOCKS_PER_SEC);
for(int i = 100000000;i>0;i--){
getpid();
}
t = clock();
printf("In point b, clock_t is %ld, second is %.2f s\n",t,(double )t/CLOCKS_PER_SEC);
return 0;
}

Output:

image-20220919021254302