linux时间和日期函数
历史上,UNX系统使用过两种不同的时间值
- 日历时间。该值是自协调世界时( Coordinated Universal Time,UTC)1970年1月1日00:000这个特定时间以来所经过的秒数累计值(早期的手册称UTC为格林尼治标准时间)。这些时间值可用于记录文件最近一次的修改时间等。系统基本数据类型time_t用于保存这种时间值。
- 进程时间。也被称为CPU时间,用以度量进程使用的中央处理器资源。进程时间以时钟滴答计算。每秒钟曾经取为50、60或100个时钟滴答,调用syscon函数得到每秒的时钟滴答数,系统基本数据类型 clock_t保存这种时间值。
当度量一个进程的执行时间时,UNX系统为一个进程维护了3个进程时间值:
-
时钟时间:时钟时间又称为墙上时钟时间( wall clock time),它是进程运行的时间总量,其值与系统中同时运行的进程数有关。每当在本书中提到时钟时间时,都是在系统中没有其他活动时进行
度量的。 - 用户CPU时间:执行用户指令所用的时间总量。
- 系统CPU时间:为该进程执行内核程序所经历的的时间。用户用户CPU时间+系统CPU时间=CPU时间
1.times函数
#include <sys/times.h>
clock_t times(struct tms *buf)
返回值:若成功则返回墙上时钟时间(单位:时钟滴答数),如果出错则返回-1。此函数填写由buf指向的tms结构体,该结构体定义如下:
struct tms
{
clock_t tms_utime; // tms_utime记录的是进程执行用户代码的时间.
clock_t tms_stime; // tms_stime记录的是进程执行内核代码的时间.
clock_t tms_cutime; // tms_cutime记录的是子进程执行用户代码的时间.
clock_t tms_cstime; // tms_cstime记录的是子进程执行内核代码的时间.
}
此函数常用来计算进程运行的时间。
#include <stdio.h>
#include <unistd.h>
#include <sys/times.h>
#include <stdlib.h>
int main()
{
clock_t start, end;
int i;
struct tms tmsstart, tmsend;
if(0 == (start = times(&tmsstart)))
printf("times error start\n");
sleep(5);
if(0 == (end = times(&tmsstart)))
printf("times error end\n");
printf("real: %7.2fs\n", (end-start)/100.0);
return 0;
}
运行结果:
2.time函数 time函数返回当前时间和日期
#include<time.h>
time_t time(time_t *calptr);
返回值:若成功,返回时间值;若出错,返回-1。时间值作为函数值返回。如果参数非空,则时间值也存放在由calptr指向的单元内。
时钟通过clockid_t 类型进行标识。如下图
3.clock_gettime函数
clock_gettime函数可用于获取指定时钟的时间,返回的时间在timespec结构中,它把时间表示为秒和纳秒。
#include<sys/time.h>
int clock_gettime(clockid_t clock_id, struct timespce *tsp);
返回值:若成功返回0;若出错,返回-1。当时钟ID设置为CLOCK_REALTIME时,clock_gettime函数提供了与time函数类似的功能,不过在系统支持高精度时间值的情况下,clock_gettime可能比time函数得到更高精度的时间值。
4.clock_getres函数
#include<sys/time.h>
int clock_getres(clockid_t clock_id, struct timespec *tsp);
//返回值:若成功,返回0;若出错,返回-1
clock_getres 函数把参数tsp指向的timespec结构初始化为与clock_id参数对应的时钟精度。例如,如果精度为1毫秒,则tv_sec字段就是0,tv_nsec字段就是1 000000。
5.clock_settime函数
要对特定的时钟设置时间,可以调用clock_settime函数。
int clock_settime(clockid_t clock_id, const struct timespec *tsp);
//返回值:若成功,返回0;若出错,返回-1
6.gettimeofday函数
gettimeofday函数与time函数相比,gettimeofday提供了更高的精度(可到微妙级)。
#include<sys/time.h>
int gettimeofday(struct timeval *restrict tp, void *restrict tzp);
//返回值:总是返回0
tzp的唯一合法值是NULL,其他值将产生不确定结果。 gettimeofday函数以距特定时间(1970年1月1日00:00:00)的秒数的方式将当前时间存放在fp指向的timeval结构中,而该结构将当前时间表示为秒和微妙。一旦取得这种从上述特定时间经过的描述的整型时间值后,通常要调用函数将其转换为分解的时间结构,然后调用另一个函数生成人们可读的时间和日期。 两个函数localtime和gmtime将日历时间转换为分解的时间,并将这些存放在一个tm结构中。
struct tm
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
7.localtime和gmtime函数
#include<time.h>
struct tm *gmtime(const time_t *calptr);
struct tm *localtime(const time_t *calptr)
//两个函数的返回值:指向分解的tm结构的指针:若出错,返回NULL
localtime 和 gmtime之间的区别是:localtime将日历时间转换成本地时间,而gmtime则将日历时间转换成协调同一时间的年、月、日、时、分、秒、周日分解结构。
8.mktime函数
函数mktime以本地时间的年月日作为参数,将其变换为time_t值。
#include<time.h>
time_t mktime(struct tm *tmptr);
//返回值:若成功,返回日历时间;若出错,返回-1
9.strftime函数
函数strftime时一个类似于printf的时间值函数。它非常复杂,可以通过可用的多个参数来定制产生的字符串。
#include<time.h>
size_t strftime(char *restrict buf,size_t maxsize,const char *restrict format,const struct tm *restrict tmptr);
size_t strftime_l(char *restrict buf,size_t maxsize,const char *restrict format,const struct tm *restrict tmptr, locale_t locale);
- strftime_l允许调用者将区域指定为参数,除此之外,strftime和strftime_l 函数是相同的。strftime使用通过TZ环境变量指定的区域。
- tmptr参数是要格式化的时间值,由一个指向分解时间值tm结构的指针说明。格式化结果存放在一个长度为maxsize个字符的buf数组中,如果buf长度足以存放格式化结果及一个null终止符,则该函数返回buf中存放的字符数;否则该函数返回0.
- format参数控制时间值的格式。如图printf函数一样,转换说明的形式是百分号之后跟一个特定字符。format中的其他字符则按原样输出。两个连续的百分号在输出中产生一个百分号。与printf函数不同之处是,每个转换说明产生一个不同的定长输出字符串,在format字符串中没有字段宽度修饰符。
各个时间函数的关系如图所示:
例:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
time_t t;
struct tm *tmp;
char buf1[16];
char buf2[64];
time(&t); // 日历时间
tmp=localtime(&t); // 分解时间
if (strftime(buf1,16,"time and date:%r,%a %b %d, %Y", tmp) == 0)
printf("buffer length 16 is too small \n");
else
printf("%s\n",buf1);
if (strftime(buf2,64,"time and date:%r,%a %b %d, %Y", tmp) == 0)
printf("buffer length 64 is too small \n");
else
printf("%s\n",buf2);
exit(0);
}
运行结果:
例(UNIX 8.17实例):
#include "apue.h"
#include <sys/times.h>
static void pr_times(clock_t, struct tms *, struct tms *);
static void do_cmd(char *);
int main(int argc, char *argv[])
{
int i;
setbuf(stdout, NULL);
for (i = 1; i < argc; i++)
do_cmd(argv[i]); /* once for each command-line arg */
exit(0);
}
static void do_cmd(char *cmd) /* execute and time the "cmd" */
{
struct tms tmsstart, tmsend;
clock_t start, end;
int status;
printf("\ncommand: %s\n", cmd);
if ((start = times(&tmsstart)) == -1) /* starting values */
err_sys("times error");
if ((status = system(cmd)) < 0) /* execute command */
err_sys("system() error");
if ((end = times(&tmsend)) == -1) /* ending values */
err_sys("times error");
pr_times(end-start, &tmsstart, &tmsend);
pr_exit(status);
}
static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend)
{
static long clktck = 0;
if (clktck == 0) /* fetch clock ticks per second first time */
if ((clktck = sysconf(_SC_CLK_TCK)) < 0) // 每秒对应的时钟tick数
err_sys("sysconf error");
printf(" real: %7.2f\n", real / (double) clktck);
printf(" user: %7.2f\n",
(tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck);
printf(" sys: %7.2f\n",
(tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck);
printf(" child user: %7.2f\n",
(tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck);
printf(" child sys: %7.2f\n",
(tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck);
}
运行结果: