//Timekeeping
// Timekeeping子系统负责更新xtime, 调整误差, 及提供get/settimeofday接口.
//Times in Kernel
//kernel的time基本类型:
// 1) system time
// A monotonically increasing value that represents the amount of time the system has been running.
// 单调增长的系统运行时间, 可以通过time source, xtime及wall_to_monotonic计算出来.
// 2) wall time
// A value representing the the human time of day, as seen on a wrist-watch. Realtime时间: xtime.
// 3) time source
// A representation of a free running counter running at a known frequency, usually in hardware, e.g GPT.
// 可以通过clocksource->read()得到counter值
// 4) tick
// A periodic interrupt generated by a hardware-timer, typically with a fixed interval defined by HZ: jiffies
// 这些time之间互相关联, 互相可以转换:
// system_time = xtime + cyc2ns(clock->read() - clock->cycle_last) + wall_to_monotonic;
// real_time = xtime + cyc2ns(clock->read() - clock->cycle_last)
// 也就是说real time是从1970年开始到现在的nanosecond, 而system time是系统启动到现在的nanosecond.
// 这两个是最重要的时间, 由此hrtimer可以基于这两个time来设置过期时间. 所以引入两个clock base.
// 参考:http://blog.csdn.net/hongjiujing/article/details/7070746
// 全局timekeeper
1.1 struct timekeeper timekeeper;
// timekeeper框架初始化
// 初始化clocksource
// 调用路径:start_kernel->timekeeping_init
// 函数任务:
// 1.使用默认时间源初始化全局timekeeper
// 2.初始化墙上时间xtime
// 3.初始化wall_to_monotonic,使其与xtime相加得到系统启动以来的单调时间
// 注:
// Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,
// 它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,
// 它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒).
1.2 static void __init timekeeping_init(void)
{
struct clocksource *clock;
unsigned long flags;
struct timespec now, boot;
//通过cmos获取当前时间
read_persistent_clock(&now);
//系统启动时的时间
read_boot_clock(&boot);
write_seqlock_irqsave(&xtime_lock, flags);
//ntp初始化
ntp_init();
//x86架构下默认的时钟源,jiffies_clocksource
clock = clocksource_default_clock();
//使能时钟源
if (clock->enable)
clock->enable(clock);
//使用clocksource初始化全局timekeeper
timekeeper_setup_internals(clock);
//初始化墙上时间
xtime.tv_sec = now.tv_sec;
xtime.tv_nsec = now.tv_nsec;
raw_time.tv_sec = 0;
raw_time.tv_nsec = 0;
//如果体系结构没有提供read_boot_clock,设置启动时间为当前时间
if (boot.tv_sec == 0 && boot.tv_nsec == 0) {
boot.tv_sec = xtime.tv_sec;
boot.tv_nsec = xtime.tv_nsec;
}
//通过将wall_to_monotonic加到xtime,获取系统启动以来的单调时间
set_normalized_timespec(&wall_to_monotonic,
-boot.tv_sec, -boot.tv_nsec);
total_sleep_time.tv_sec = 0;
total_sleep_time.tv_nsec = 0;
write_sequnlock_irqrestore(&xtime_lock, flags);
}
// timekeeper初始化
// 函数任务:
// 1.绑定timekeeper到clocksource
// 2.换算NTP间隔为clocksource的cycle
// 调用路径:timekeeping_init->timekeeper_setup_internals
// 注:
// 1.timekeeper.cycle_interval,一个NTP间隔对应的时钟cycle
// 2.timekeeper.xtime_interval, 一个NTP间隔对应的时钟cycle*mult
// 3.timekeeper.raw_interval, 一个NTP间隔(近似值)
1.3 static void timekeeper_setup_internals(struct clocksource *clock)
{
cycle_t interval;
u64 tmp;
//timekeeper使用提供的时钟源
timekeeper.clock = clock;
clock->cycle_last = clock->read(clock);
//NTP_INTERVAL_LENGTH转换为clocksource的cycle
tmp = NTP_INTERVAL_LENGTH;
tmp <<= clock->shift;
tmp += clock->mult/2;
do_div(tmp, clock->mult);
if (tmp == 0)
tmp = 1;
//一个NTP间隔对应的时钟cycle
interval = (cycle_t) tmp;
timekeeper.cycle_interval = interval;
//一个NTP间隔对应的xtime间隔
timekeeper.xtime_interval = (u64) interval * clock->mult;
//
timekeeper.raw_interval =
((u64) interval * clock->mult) >> clock->shift;
timekeeper.xtime_nsec = 0;
//使用时钟源的shift
timekeeper.shift = clock->shift;
//累积的时间相对于NTP的误差
timekeeper.ntp_error = 0;
timekeeper.ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
timekeeper.mult = clock->mult;
}
时间子系统9_timekeeper初始化
最新推荐文章于 2023-04-08 17:16:47 发布