閱讀655 返回首頁    go 阿裏雲 go 技術社區[雲棲]


時間子係統9_timekeeper初始化

//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.
//	參考:https://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;

}

最後更新:2017-04-03 14:54:25

  上一篇:go 時間子係統3_低分辨率定時框架初始化
  下一篇:go 移動GIS開發環境配置