chrony v3.5 源代码分析

2024-06-03  本文已影响0人  RonZheng2010

1 数组

ARR_Instance定义数组。

typedef struct ARR_Instance_Record *ARR_Instance; 

它最终的定义是ARR_Instance_Record,它管理一个动态分配的数组。

2 日志

2.1 LOG模块

LOG模块保存一般的日志。
日志可以写入用户指定的日志文件中。如果没有指定,则可以写入系统日志中。

2.2 LogFile

除了一般的日志,某些模块,如refclocks,rtc等还有自己独立的日志文件。LogFile用于保存这些日志。

LogFile实例保存在数组logfiles中,每个模块一个实例。

struct LogFile logfiles[6];

3 配置文件

3.1 CNF_ParseLine()

如下是chrony配置文件的一个例子。

# chrony.conf

pool ntp.ubuntu.com          iburst maxsources 4
pool 0.ubuntu.pool.ntp.org iburst maxsources 1
pool 1.ubuntu.pool.ntp.org iburst maxsources 1
pool 2.ubuntu.pool.ntp.org iburst maxsources 2

refclock PPS /dev/pps0 lock NMEA refid PPS
refclock SHM 0 refid NMEA noselect

rtcsync

CNF_ParseLine()解析配置文件中的一行。

3.1 parse_refclock()

在parse_refclock()中,

static ARR_Instance refclock_sources;

RefclockParameters保存参考时钟源的配置参数。

关于以上配置文件的其他说明。

3 定时器

3.1 TimerQueueEntry

TimerQueueEntry保存定时器。

tqe_free_list保存可用的定时器,而timer_queue保存使用中的定时器。n_timer_queue_entries是timer_queue中的定时器数量。
为了方便给定时器分配id, next_tqe_id保存当前定时器最大编号。

TimerQueueEntry timer_queue;
unsigned long n_timer_queue_entries;
TimerQueueEntry *tqe_free_list;
SCH_TimeoutID next_tqe_id;

allocate_tqe()从tqe_free_list中得到一个可用的定时器。如果tqe_free_list还没有分配,会先分配它。

3.2 SCH_AddTimeout()

SCH_AddTimeout()启动一个定时器。

SCH_AddTimeout()的参数指定的时间戳是一个绝对时间,而SCH_AddTimeoutByDelay()指定了一个相对时间。

3.3 dispatch_timeouts()

dispatch_timeouts() 派发到期的定时器。在while()循环中,

4 参考时钟源 Reference Clock

4.1 RCL_Instance_Record 与RefclockDriver

参考时钟源保存在全局数组reflocks中。

ARR_Instance refclocks;

它的类型是RCL_Instance_Record。

RefclockDriver可以是如下的驱动模块:SHM类型对应RCL_SHM_driver、PPS类型对应RCL_PPS_driver,SOCK类型对应RCL_SOCK_driver。

4.2 CNF_AddRefclocks()

CNF_AddReflocks() 根据数组refclock_sources创建参考时钟,也就是RCL_Instance_Record实例。

在RCL_AddRefclock()中,

4.3 RCL_SHM_driver

RCL_SHM_driver是SHM类型时钟源的驱动模块。

它的init()函数是shm_initialise()。

#define SHMKEY 0x4e545030            // 这实际上是字符串”NTP0”

shm_poll() 从共享内存块读时间戳数据的原始样本,并累积。

4.4 RCL_PPS_driver

PPS类型时钟源的init()是pps_initialise()。

pps_poll() 在每次PPS脉冲来到时,从它参考的时钟源累积原始样本。

RCL_AddCookedPulse()结合参考时钟源的时间戳,累积原始样本。

refclock SHM 0 refid NMEA noselect 
refclock PPS /dev/pps0 lock NMEA refid PPS

4.5 RCL_StartRefclocks()

RCL_StartRefclocks()启动参考时钟源。

4.5 poll_timeout()

定时器超时时,poll_timeout()被调用。

4.6 SPF_GetFilteredSample()

SPF_GetFilteredSample() 过滤原始样本,计算可以用于授时的样本。

4.6 LCL_SetSyncStatus()

系统时间是否授时成功有一个状态标志,可以使用timedatectl,可以查看这个状态,如下面图中的System clock synchronizaition。

LCL_SetSyncStatus()设置这个状态。

# /etc/default/chrony.conf
rtcsync

chronyd启动时调用REF_Initialize()。

4.7 SRC_SelectSource()

SRC_SelectSource()比较备选参考时间源,根据打分选择一个作为当前时间源。

refclock SHM 0 refid NMEA noselect 

4.8 SRC_SetReference()

REF_SetReference()调整系统时间,并设置同步状态。在同步状态为false时,可能直接调整到位,在状态为true时,会逐步接近。

5 main()

main()函数的步骤如下。

上一篇下一篇

猜你喜欢

热点阅读