//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; }
时间: 2024-11-02 14:47:45