在前面的文章中,我们介绍了Linux获取时间的种类,最后提到了时钟源的概念,也就是我们获取的时间的计时器的源头。Linux使用clocksource来抽象计时的硬件,这就是本篇要讲的内容。原本想在本篇写出一点不一样的东西,但是发现Linux时间子系统之(十五):clocksource已经讲得很好了,所以本篇转载了它的内容,适配了5.10,同时增加了一些内容。
1. clocksource数据结构
clock source是在指定输入频率的clock下工作的一个计时器的抽象。输入频率可以确定以什么样的精度来划分时间(假设输入counter的频率是1GHz,那么一个cycle就是1ns,也就是说时间精度是用1ns来划分的,最大的精度就是1ns)。
struct clocksource {
u64 (*read)(struct clocksource *cs); -----------------(1)
u64 mask;
u32 mult;
u32 shift;
u64 max_idle_ns;
u32 maxadj;
u32 uncertainty_margin;
#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
struct arch_clocksource_data archdata;
#endif
u64 max_cycles;
const char *name; --------------------------(2)
struct list_head list;
int rating;
enum vdso_clock_mode vdso_clock_mode;
u16 vdso_fix;
u16 vdso_shift;
unsigned long flags;
int (*enable)(struct clocksource *cs);
void (*disable)(struct clocksource *cs);
void (*suspend)(struct clocksource *cs);
void (*resume)(struct clocksource *cs);
void (*mark_unstable)(struct clocksource *cs);
void (*tick_stable)(struct clocksource *cs);
/* private: */
#ifdef CONFIG_CLOCKSOURCE_WATCHDOG ---------------(3)
/* Watchdog related data, used by the framework */
struct list_head wd_list;
u64 cs_last;
u64 wd_last;
#endif
struct module *owner;
};
struct clocksource的成员分成3组,我们分别介绍:
(1)这部分的代码是和计时有关的,kernel会频繁的访问这些数据结构,对于clock source抽象的counter而言,其counter value都是针对clock计数的,具体一个clock有多少个纳秒是和输入频率相关的。
通过read获取当前的counter value,这个计数值是基于cycle的(数据类型是cycle_t,U64)。不过,对于用户和其他driver而言,cycle数据是没有意义的,最好统一使用纳秒这样的单位,因此在struct clocksource中就有了mult和shift这两个成员了。我们先看