linux获取时钟接口
概述
linux系统开发环境中,需要获取各种类型时钟,针对这些情况做了一个简单整理。
首先对时钟接口的需求大概包括有:
1:获取当前时钟,这个在内核中一般表现为UTC时钟(从1970.1.1 00:00:00到当前时间的秒及纳秒)
2:获取系统启动后单调时钟,即系统启动以来的秒和纳秒数
3:设置时钟
4:针对时钟不同结构体数据之间的转换
时区
时区分类:
UTC:
整个地球分为二十四时区,每个时区都有自己的本地时间。在国际无线电通信场合,为了统一起见,使用一个统一的时间,称为通用协调时(UTC, Universal Time Coordinated)
GMT:
格林威治标准时间 (Greenwich Mean Time)指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。(UTC与GMT时间基本相同,本文中不做区分)
CST:
中国标准时间 (China Standard Time)
DST:
夏令时(Daylight Saving Time) 指在夏天太阳升起的比较早时,将时钟拨快一小时,以提早日光的使用。(中国不使用)
GMT + 8 = UTC + 8 = CST
linux系统时钟一般操作
读写时钟
//查看时钟
kongcb@tcu-Lenovo:~$ date
2022年 05月 17日 星期二 14:17:25 CST
kongcb@tcu-Lenovo:~$ date -R
Tue, 17 May 2022 14:17:30 +0800 //+0800表示东八区时区
//设置时钟
kongcb@tcu-Lenovo:~$ sudo date -s "20220517 14:25"
[sudo] password for kongcb:
2022年 05月 17日 星期二 14:25:00 CST
kongcb@tcu-Lenovo:~$ date -R
Tue, 17 May 2022 14:25:08 +0800
时区操作
kongcb@tcu- Lenovo: ~ $ timedatectl
Local time: 二 2022 - 05 - 17 14 : 26 : 17 CST
Universal time: 二 2022 - 05 - 17 06 : 26 : 17 UTC
Timezone: Asia/ Chongqing ( CST, + 0800 )
NTP enabled: yes
NTP synchronized: no
RTC in local TZ: no
DST active: n/ a
kongcb@tcu- Lenovo: ~ $ sudo timedatectl set- timezone Asia/ Shanghai
kongcb@tcu- Lenovo: ~ $ timedatectl
Local time: 二 2022 - 05 - 17 14 : 31 : 43 CST
Universal time: 二 2022 - 05 - 17 06 : 31 : 43 UTC
Timezone: Asia/ Shanghai ( CST, + 0800 )
NTP enabled: yes
NTP synchronized: no
RTC in local TZ: no
DST active: n/ a
kongcb@tcu- Lenovo: ~ $ timedatectl list- timezones
Africa/ Abidjan
Africa/ Accra
Africa/ Addis_Ababa
. . . . . . . .
同步网络时钟
kongcb@tcu- Lenovo: ~ $ sudo apt- get install ntp
Reading package lists. . . Done
Building dependency tree
. . . . . . . .
kongcb@tcu- Lenovo: ~ $ ntpdate - d cn. pool. ntp. org
17 May 14 : 39 : 36 ntpdate[ 12707 ] : ntpdate 4.2 .6 p5@1.2349 - o Wed Oct 9 18 : 57 : 00 UTC 2013 ( 1 )
Looking for host cn. pool. ntp. org and service ntp
host found : 111.230 .189 .174
transmit ( 111.230 .189 .174 )
receive ( 111.230 .189 .174 )
transmit ( 94.237 .64 .20 )
. . . . . . .
server 94.237 .64 .20 , port 123
stratum 2 , precision - 25 , leap 00 , trust 000
refid [ 94.237 .64 .20 ] , delay 0.12453 , dispersion 0.00023
transmitted 4 , in filter 4
reference time: e62dbdc3. f523cdc3 Tue, May 17 2022 14 : 22 : 59.957
originate timestamp: e62dc0b0. 235 c07cd Tue, May 17 2022 14 : 35 : 28.138
transmit timestamp: e62dc1af. 3064 ec71 Tue, May 17 2022 14 : 39 : 43.189
filter delay: 0.12569 0.12532 0.12471 0.12453
0.00000 0.00000 0.00000 0.00000
filter offset: - 255.100 - 255.100 - 255.100 - 255.100
0.000000 0.000000 0.000000 0.000000
delay 0.12453 , dispersion 0.00023
offset - 255.100391
kongcb@tcu- Lenovo: ~ $ sudo ntpdate - u cn. pool. ntp. org
17 May 14 : 38 : 23 ntpdate[ 12737 ] : adjust time server 202.118 .1 .81 offset 0.000369 sec
kongcb@tcu- Lenovo: ~ $ date
2022 年 05 月 17 日 星期二 14 : 38 : 27 CST
ntp常用服务器
//国内
cn.pool.ntp.org 中国开源免费NTP服务器
ntp1.aliyun.com 阿里云NTP服务器
ntp2.aliyun.com 阿里云NTP服务器
time1.aliyun.com 阿里云NTP服务器
time2.aliyun.com 阿里云NTP服务器
//海外
pool.ntp.org 开源免费NTP服务器
time1.apple.com 苹果NTP服务器
time2.apple.com 苹果NTP服务器
time3.apple.com 苹果NTP服务器
time4.apple.com 苹果NTP服务器
time5.apple.com 苹果NTP服务器
time1.google.com 谷歌NTP服务器
time2.google.com 谷歌NTP服务器
time3.google.com 谷歌NTP服务器
time4.google.com 谷歌NTP服务器
linux应用程序时钟操作
接口类型
接口相关头文件
# include <time.h>
相关数据结构体定义:
timespec结构包括:
struct timespec {
time_t tv_sec;
long tv_nsec;
} ;
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
long tm_year;
int tm_wday;
int tm_yday;
} ;
函数原型:
int clock_gettime ( clockid_t clk_id, struct timespec * tp) ;
其中,cld_id类型有一下几种:
# define CLOCK_REALTIME 0
# define CLOCK_MONOTONIC 1
# define CLOCK_PROCESS_CPUTIME_ID 2
# define CLOCK_THREAD_CPUTIME_ID 3
# define CLOCK_MONOTONIC_RAW 4
# define CLOCK_REALTIME_COARSE 5
# define CLOCK_MONOTONIC_COARSE 6
# define CLOCK_BOOTTIME 7
注意:对于CLOCK_MONOTONIC时钟,系统启动后置0 ,之后累加,但也并非不能修改,有几种情况会有修改:
1 :时钟的clock- source修改了,比如时钟从高频时钟源转到低频的
2 :timezone修改了,如从local time修改为UTC time
不过一般正常操作不会碰到这种情况了,且嵌入式设备系统一般不会配置ntp等等,实际上想操作也不行
获取时钟
struct timespec time;
int nRet = clock_gettime ( CLOCK_REALTIME_COARSE, & time) ;
time_t ttSec = time. tv_sec;
int nRet = clock_gettime ( CLOCK_REALTIME, & time) ;
long long llmSec = time. tv_sec* 1000 + time. tv_nsec/ 1000000 ;
int nRet = clock_gettime ( CLOCK_MONOTONIC_COARSE, & time) ;
time_t ttSecMon = time. tv_sec;
int nRet = clock_gettime ( CLOCK_MONOTONIC, & time) ;
long long llmSecMonCnt = time. tv_sec* 1000 + time. tv_nsec/ 1000000 ;
设置时钟
# include <time.h>
int stime ( time_t * t)
time_t timelocal ( struct tm * tm) ;
time_t timegm ( struct tm * tm) ;
char * asctime ( const struct tm * tm) ;
char * asctime_r ( const struct tm * tm, char * buf) ;
char * ctime ( const time_t * timep) ;
char * ctime_r ( const time_t * timep, char * buf) ;
struct tm * gmtime ( const time_t * timep) ;
struct tm * gmtime_r ( const time_t * timep, struct tm * result) ;
struct tm * localtime ( const time_t * timep) ;
time_t mktime ( struct tm * tm) ;
实例代码
# include <time.h>
# include <stdio.h>
# include <stdlib.h>
int main ( )
{
struct timespec tstmtime, tsMonTime;
struct tm * pCurTime;
time_t ttSec, ttSecMonCnt, timet;
long lmSecCnt;
int nRet = 0 ;
nRet = clock_gettime ( CLOCK_REALTIME, & tstmtime) ;
ttSec = tstmtime. tv_sec;
lmSecCnt = tstmtime. tv_sec* 1000 + tstmtime. tv_nsec/ 1000000 ;
printf ( "currtime-time-spec: second:%d, mSec:%ld \n" , ( int ) ttSec, lmSecCnt) ;
nRet = clock_gettime ( CLOCK_MONOTONIC_COARSE, & tsMonTime) ;
ttSecMonCnt = tsMonTime. tv_sec;
printf ( "monotonic second :%d \n" , ( int ) ttSecMonCnt) ;
pCurTime = localtime ( & ttSec) ;
printf ( "localtime:%d-%d-%d %02d:%02d:%02d \n" ,
pCurTime-> tm_year+ 1900 ,
pCurTime-> tm_mon+ 1 ,
pCurTime-> tm_mday,
pCurTime-> tm_hour,
pCurTime-> tm_min,
pCurTime-> tm_sec) ;
pCurTime = gmtime ( & ttSec) ;
printf ( "gmtime:%d-%d-%d %02d:%02d:%02d \n" ,
pCurTime-> tm_year+ 1900 ,
pCurTime-> tm_mon+ 1 ,
pCurTime-> tm_mday,
pCurTime-> tm_hour,
pCurTime-> tm_min,
pCurTime-> tm_sec) ;
timet = mktime ( pCurTime) ;
printf ( "mktime-utc:get time_t:%d \n" , ( int ) timet) ;
pCurTime = localtime ( & ttSec) ;
timet = mktime ( pCurTime) ;
printf ( "mktime-location:get time_t:%d \n" , ( int ) timet) ;
getchar ( ) ;
}
执行结果
kongcb@tcu- Lenovo: / home/ clou- tcu/ kongchengbo/ test- code/ time$ gcc time- test. c - o timetest
kongcb@tcu- Lenovo: / home/ clou- tcu/ kongchengbo/ test- code/ time$ . / timetest
currtime- time- spec: second: 1652783615 , mSec : - 778793352
monotonic second : 443800
localtime : 2022 - 5 - 17 18 : 33 : 35
gmtime : 2022 - 5 - 17 10 : 33 : 35
mktime- utc: get time_t : 1652754815
mktime- location: get time_t : 1652783615
如上可知:
1 :CLOCK_MONOTONIC 获取启动依赖的秒数
2 :本地时间 ( 我们是北京时间) 和UTC 时间差8 小时
3 :不同接口操作location time和UTC time