Linux时间
Linux衡量时间的三种方式:墙钟时间、进程时间、单调时间
Linux的绝对时间:新纪元至今经过的秒数。
新纪元(格林威治时间):1970年1月1日0时
时间的数据结构
原始表示
typedef long time_t;
32位长整型数,time_t最多能表示新纪元后2147483647秒,大约会在2038年溢出。
微秒级精度
#include <sys/time.h>
struct timeval{
time_t tv_sec;
suseconds_t tv_usec;
};
纳秒级精度
#include <time.h>
struct timespec{
time_t tv_sec;
long tv_nsec;
}
标准C提供的便于理解的时间格式
#include <time.h>
struct tm{
int tm_sec; //0~59
int tm_min; //0~59
int tm_hour; //0~23
int tm_mday; // the day of the month,0~31
int tm_mon; //0~11
int tm_year;
int tm_wday; //the day of the week,0~6
int tm_yday; //the day in the year,0~365
int tm_isdst;
#ifdef _BSD_SOURCE
long tm_gmtoff;
const char *tm_zone;
#endif
};
进程时间类型
clock_t,长整型。
待查资料。
POSIX时钟
clockid_t类型标识特定的POSIX时钟,共五种
CLOCK_REALTIME
CLOCK_MONOTONIC
CLOCK_MONOTONIC_RAW
CLOCK_PROCESS_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID
POSIX标准中,只有CLOCK_REALTIME是必须实现的。
时间源精度
#include <time.h>
int clock_getres(clockid_t clock_id,struct timespec *res);
//成功调用,将会将clock_id指定的时钟精度保存到res。成功返回0,失败返回-1。
#include <stdio.h>
#include <time.h>
clockid_t clocks[] = {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID,
CLOCK_MONOTONIC_RAW,
(clockid_t) -1
};
int main(){
int i;
for(i=0;clocks[i] != (clockid_t)-1;i++){
struct timespec res;
int ret;
ret = clock_getres(clocks[i],&res);
if(ret)
perror("clock_getres");
else
printf("clock=%d sec=%ld nsec=%ld\n",clocks[i],res.tv_sec,res.tv_nsec);
return 0;
}
return 0;
}
1 c_clock_id : c_clock_id.c
2 gcc -Wall -w -lrt -g -o c_clock_id c_clock_id.c
3 //所有使用posi时钟的函数都需要将目标文件与librt链接,下同
4 run :
5 ./c_clock_id
6
7 clean :
8 rm c_clock_id
有点问题。
取得当前时间
time函数(秒级)
#include <time.h>
time_t time(time_t *t);
//如果参数t是NULL,返回从新纪元以来流逝的秒数。否则将秒数写入到参数t中。
#include <stdio.h>
#include <time.h>
int main(){
time_t t;
printf("%ld\n",(long)time(&t));
printf("%ld\n",(long)time(NULL));
printf("%ld\n",(long)t);
return 0;
}
结果正常。
gettimeofday函数(微秒级)
#include <sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz);
//成功调用时,当前时间赋给tv指向的结构体,并返回0,timezone已经弃用,传递NULL。
//失败时,返回-1。
#include <stdio.h>
#include <sys/time.h>
int main(){
struct timeval tv;
int ret;
ret = gettimeofday(&tv,NULL);
if(ret)
perror("gettimeofday");
else
printf("seconds=%d,useconds=%ld\n",(long)tv.tv_sec,(long)tv.tv_usec);
return 0;
}
clock_gettime函数(纳秒级)
#include <time.h>
int clock_gettime(clockid_t clock_id,strutc timespec *ts);
//获取指定时间源的时间,成功调用时,返回0,并将指定时间源的当前时间存储到ts中。
//失败返回-1。
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
clockid_t clocks[] = {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID,
CLOCK_MONOTONIC_RAW,
(clockid_t) -1
};
int main(){
struct timespec ts;
int ret;
int i;
for(i=0;clocks[i] != (clockid_t)-1;i++){
ret = clock_gettime(clocks[i],&ts);
if(ret)
perror("clock_gettime");
else
printf("clock=%d,sec=%ld,nsec=%ld\n",clocks[i],(long)ts.tv_sec,(long)ts.tv_nsec);
}
return 0;
}
获得进程时间
#include <sys/time.h>
struct tms{
clock_t tms_utime; //用户时间
clock_t tms_stime; //系统时间
clock_t tms_cutime; //子进程用户时间
clock_t tms_cstime; //子进程系统时间
};
clock_t times(struct tms *buf);
//获得正在运行的当前进程机器子进程的进程时间
//调用成功,将发起进程及其子进程消耗的进程时间写入到buf所指向的tms结构体中。
//调用失败。返回-1。
时间统计分为用户时间和系统时间:
用户时间:在用户空间执行代码所用的时间
系统时间:在内核空间执行所用的时间
子进程耗时统计,是在该子进程已经结束,且父进程对其调用了waitpid()之后才执行。
设置当前时间
stime函数(秒级)
#define _SVID_SOURCE
#include <time.h>
int stime(time_t *t);
//成功调用,返回0,系统时间被设置为t所指的值。
//失败返回-1.
执行 man stime,可以看到修改时间时,不建议使用stime函数:
使用会显示如下错误:
settimeofday函数(微秒级)
#include <sys/time.h>
int settimeofday(const struct timeval *tv,const struct timezone *tz);
//tz 传递NULL
//成功返回0,失败返回-1
#include <stdio.h>
#include <sys/time.h>
int main(){
struct timeval tv = { .tv_sec = 31415926,
.tv_usec = 27182818 };
int ret;
ret = settimeofday(&tv,NULL);
if(ret)
perror("settimeofday");
return 0;
}
报错:
clock_settime函数(纳秒级)
#include <time.h>
int clock_settime(clockid_t clock_id,const struct timespec *ts);
//成功返回0,失败返回-1