时间分类
- real time 和 处理器时间(process time)
从某个点测量的真实时间,比如从1970年开始的,或者从进程启动时候的点开始;
进程使用CPU的时间,分用户时间(运行在用户态)和系统时间(运行在内核态) - 硬件时间(hardware clock)
一个带电池的硬件,内核在启动时候从这里初始化开始时间 - 软件时间(software clock, HZ, jiffy)
大多数系统调用设置超时和测量时间的精度取决于HZ,是内核维护的一个最小精度,HZ取决于操作系统和硬件,最早是100,后来有100,250,300,1000 - 高精度定时器
在 2.6.21 之前,定时器的精度取决于 jiffy; 从这个版本开始, linux支持使用高精度定时器硬件来设置定时器 - Epoch
1970-01-01 00:00:00 +0000 (UTC) 开始的秒数 - Broken-down time
struct tm 描述时间的各个部分,年月日分开
几个时间结构
clock_t CPU时钟滴答
要知道过了多少秒,需要除 CLOCKS_PER_SECstruct tms 进程运行时间
1
2
3
4
5
6struct tms {
clock_t tms_utime; /* user time */
clock_t tms_stime; /* system time */
clock_t tms_cutime; /* user time of children */
clock_t tms_cstime; /* system time of children */
};struct timeval 精确到微秒
1
2
3
4struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};struct timespec 精确到纳秒
1
2
3
4struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};time_t 时间戳,精确到秒
struct tm brokentime,年月日
struct itimerspec 定时器使用,精确到纳秒
struct itimerspec {
struct timespec it_interval; /* Timer interval /
struct timespec it_value; / Initial expiration */
};
时间应用的地方
获取墙上时间
(2)time_t time(time_t *t); // 精确到秒
(2)int clock_gettime(clockid_t clk_id, struct timespec *tp); // 精确到纳秒,推荐
(2)int gettimeofday(struct timeval *tv, struct timezone *tz); // 精确到毫秒,不再推荐获取程序运行CPU时间(用户、系统)
(2)clock_t clock(void); // 最简单的CPU时间,会回绕
(2)clock_t times(struct tms *buf); // 获取CPU时间, 还知道child的时间, clock_t
(2)int getrusage(int who, struct rusage *usage); // 跟times获取的结果差不多, 但不知道child的
(3)int clock_getcpuclockid(pid_t pid, clockid_t *clock_id); // 获取某个进程的定时器,配合clock_gettime(2)也能知道CPU时间
- 定时器
// 精确到毫秒, 信号通知
(2)int getitimer(int which, struct itimerval *curr_value);
(2)int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
// 精确到纳秒,信号通知
(2)int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);
(2)int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec * old_value);
(2)int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
(2)int timer_getoverrun(timer_t timerid);
(2)int timer_delete(timer_t timerid);
// 精确到纳秒,fd通知, 可以集成到 epoll, 推荐
(2)int timerfd_create(int clockid, int flags);
(2)int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
(2)int timerfd_gettime(int fd, struct itimerspec *curr_value);
1 | // 获取当前进程占用的CPU时间,返回的值是clock,每秒的clock数量可以用 sysconf(_SC_CLK_TCK); 获取 |
1 | clockid_t: |
操作 struct timeval
1 | // res=a+b |
每进程的时钟
1 | // 获取某个进程的clockid,然后配合 clock_gettime(2) 获取该进程的cpu时间 |
定时器
1 | // 设置定时器,到期使用信号通知 |
1 | // 1. 获取时间 |
c++11的时间库chrono
3个类型
- Clocks
system_clock: 系统获取的时钟, 常用这个
steady_clock: 不能被修改的时钟
high_resolution_clock: 高精度时钟
system_clock::now() // 返回 std::chrono::time_point 获取当前时刻
system_clock::to_time_t() // 返回 std::time_t 时间戳
system_clock::from_time_t() // std::time_t变回time_point
- Time point
time_point: 特定clock从开始时间流逝的时间段
time_since_epoch() // 返回从开始时间到现在的时间间隔
time_point_cast<>
- Duration
duration: 时间段
count() // 周期数
duration_cast<>() // 转换成另一种类型的时间间隔
template<std::intmax_t Num, std::intmax_t Denom = 1> class ratio; // 分辨率,Num/Denom 秒
template<class Rep, class Period = std::ratio<1>> class duration; // 时间间隔, Rep个分辨率
常用分辨率:
typedef duration <Rep, ratio<3600,1>> hours;
typedef duration <Rep, ratio<60,1>> minutes;
typedef duration <Rep, ratio<1,1>> seconds;
typedef duration <Rep, ratio<1,1000>> milliseconds;
typedef duration <Rep, ratio<1,1000000>> microseconds;
typedef duration <Rep, ratio<1,1000000000>> nanoseconds;
std::chrono::seconds(3) // 3秒
duration.count() 获取当前分辨率下的时钟周期个数,比如 seconds(3).count() == 3, hours(4).count() == 4
- 格式化输出
auto t = chrono::system_clock::to_time_t(std::chrono::system_clock::now());
cout<< std::put_time(std::localtime(&t), “%Y-%m-%d %X”)<<endl;
cout<< std::put_time(std::localtime(&t), “%Y-%m-%d %H.%M.%S”)<<endl;