时间子系统4_timekeeper初始化(一)

2014-11-24 02:37:36 · 作者: · 浏览: 3
//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 // 3.初始化ntp字段 // 调用路径:timekeeping_init->timekeeper_setup_internals // 注: // 不通过联网ntp矫正本机时间,timekeeper与clocksource保持一致 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_inte