1.clock_gettime
#include<time.h>
int clock_gettime(clockid_t clk_id,struct timespec *tp);
struct timespec
{
time_t tv_sec; /* 秒*/
long tv_nsec; /* 纳秒*/
}
clk_id : CLOCK_BOOTTIME,以系统启动时间为时间原点的时间体系,不受其它因素的影响,计算机休眠时依然走时。
CLOCK_REALTIME,就是我们所说的自然时间,由于计算机上的时间有可能不准,所以是可以设置的,所以有可能会产生跳跃。后面所有的时间体系都是不可设置的,下面不再一一说明了。
有很多,附文末
#include<time.h>
//伪代码
while(1)
{
struct timespec now;
clock_gettime(CLOCK_BOOTTIME, &now);
long long now_time = now.tv_sec * 1000000000 + now.tv_nsec;
printf("now:%lld, sec:%lld, nsec:%lld\n", now_time, now.tv_sec, now.tv_nsec);
usleep(300000);//300ms
return now_time;
}
结构体只有秒和微妙,其中tv_nsec最高位是百毫秒位,可以看到睡眠300毫秒会加在tv_nsec最高位,它满了后,tv_sec就进一位。因此毫秒的计时并没有缺失。
CLOCK_BOOTTIME可以作为音视频帧的pts,因为它不受任何因素影响,开机后就开始计时。
2.gettimeofday
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
struct timeval
{
__time_t tv_sec; /* Seconds. 秒*/
__suseconds_t tv_usec; /* Microseconds. 微秒*/
};
struct timezone
{
int tz_minuteswest; /* Minutes west of GMT. 和Greenwich时间差了多少分钟 */
int tz_dsttime; /* Nonzero if DST is ever in effect. 日光节约时间的状态 */
};
long long get_time()
{
struct timeval tv;
gettimeofday(&tv, NULL);
ZlogInfo("second:%ld\n",tv.tv_sec); //秒
ZlogInfo("millisecond:%ld\n",tv.tv_sec*1000 + tv.tv_usec/1000); //毫秒
ZlogInfo("microsecond:%ld\n",tv.tv_sec*1000000 + tv.tv_usec); //微秒
long long temp_time = tv.tv_sec * 1000000 + tv.tv_usec;
return temp_time;
}
在第二个参数填null,可以看到它有自己的毫秒位,这个函数返回的是从UTC时间,1970/1/1,零点开始计时的时间。它其实也就是随系统时间,也就是如果你手动更改了系统时间,或者系统NTP自动联网校时了,那么这个时间就会发送跳跃。因此如果你把他当做音/视频pts是非常不合理的。
附录:
CLOCK_REALTIME: 系统相对时间,从UTC 1970-1-1 0:0:0开始计时,更改系统时间会更改获取的值;
CLOCK_MONOTONIC: 系统绝对时间/单调时间,为系统重启到现在的时间,更改系统时间对它没有影响;
CLOCK_PROCESS_CPUTIME_ID: 本进程到当前代码系统CPU花费的时间; CLOCK_THREAD_CPUTIME_ID:
本线程到当前代码系统CPU花费的时间;
CLOCK_REALTIME,就是我们所说的自然时间,由于计算机上的时间有可能不准,所以是可以设置的,所以有可能会产生跳跃。后面所有的时间体系都是不可设置的,下面不再一一说明了。CLOCK_REALTIME_ALARM、CLOCK_REALTIME_COARSE、CLOCK_TAI虽然本身是不可设置的,但是都会受到CLOCK_REALTIME设置的影响,有可能会产生跳跃。
CLOCK_REALTIME_ALARM,和CLOCK_REALTIME相同,在定时器设置时才有用,ALARM代表的是定时设置,如果目标定时时间到了的时候系统在休眠,会唤醒系统。
CLOCK_REALTIME_COARSE,和CLOCK_REALTIME相同,精度不高但是获取比较快。
CLOCK_TAI,和CLOCK_REALTIME相同,但是不考虑闰秒问题,TAI是International Atomic
Time的反向简称。CLOCK_MONOTONIC,由于前面几个时间体系都有可能会产生回跳,计算机中需要有一个单调递增的时间体系。此时间体系的时间原点并不重要,在Linux中是以系统启动的时间点作为时间原点,在计算机休眠时会暂停走时,受adjtime和NTP的影响可能会向前跳跃。
CLOCK_MONOTONIC_COARSE,同上,但是精度降低,访问更快。
CLOCK_MONOTONIC_RAW,同CLOCK_MONOTONIC,但是不受adjtime和NTP的影响。
CLOCK_BOOTTIME,以系统启动时间为时间原点的时间体系,不受其它因素的影响,计算机休眠时依然走时。
CLOCK_BOOTTIME_ALARM,同上,在定时器设置时才有用,ALARM代表的是定时设置,如果目标定时时间到了的时候系统在休眠,会唤醒系统。
CLOCK_PROCESS_CPUTIME_ID,以进程创建时间为时间原点,进程运行时走时,进程休眠时暂停走时。
CLOCK_THREAD_CPUTIME_ID,以线程创建时间为时间原点,线程运行时走时,线程休眠时暂停走时。
参考:
linux C时间编程
理解linux时间软硬件