Kernel Tour内核之旅

jiffies

What is jiffies

jiffies就是tick的counter,每个tick => jiffies+1。

tick频率在config中可以设置,默认情况下,CONFIG_HZ=250(每秒钟250个tick)

jiffies在vmlinux.lds.S中定义,实际指向了jiffies_64,在timer.c中定义。

vmlinux.lds.S:
	jiffies=jiffies_64

timer.c
	jiffies_64 = INITIAL_JIFFIES

jiffies.h
	INITIAL_JIFFIES is -300\*HZ

How jiffies update

jiffes在tick触发时更新,所以它的更新依赖于tick device,而tick device则依赖于硬件arch timer的初始化。所以在arch timer初始化之前,在timer interrupt能够产生前,或者说在tick device被创建前,jiffies是不会被更新的。

在arch timer初始化后,legacy timer开始工作,jiffies在tick_handle_periodic中被更新。

在hrtimer初始化后,tick切换到high res模式,hrtimer interrupt handler接管了原来的tick handler,tick被重新实现成了一个hrtimer(sched_timer),这之后jiffies在sched timer中更新。

Searching 39355 files for "jiffies_64 +=" (case sensitive)

# Jiffies update in high res mode
/home/cyrus/Workspace/codebase/linux-kernel/mainline/kernel/time/tick-sched.c:
  116  
  117  	/* Advance jiffies to complete the jiffies_seq protected job */
  118: 	jiffies_64 += ticks;
  119  
  120  	/*

# Jiffies update in legacy mode
/home/cyrus/Workspace/codebase/linux-kernel/mainline/kernel/time/timekeeping.c:
 2286  void do_timer(unsigned long ticks)
 2287  {
 2288: 	jiffies_64 += ticks;
 2289  	calc_global_load();
 2290  }

2 matches across 2 files

jiffies clocksource

jiffies在能够被周期更新的基础上,被实现为一个clock source,作为timekeeping默认的clocksource,为timekeeping提供低精度服务。

在arch timer clocksource注册后,timekeeping切换到精度更高的arch timer clocksource。

在启动log中,可以看到这个切换过程:

# dmesg | grep clocksource
[    0.000000] clocksource: arch_sys_counter: mask: 0x1ffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
[    0.140935] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.385832] clocksource: Switched to clocksource arch_sys_counter

CONFIG_HZ vs USER_HZ

除了CONFIG_HZ定义的内核态jiffies以外,用户态还有一个USER_HZ定义的用户态jiffies,USER_HZ默认静态定义为100,也就是一个jiffies 10ms。

通过系统调用拿到的jiffies,都是用户态jiffies,这样不论内核CONFIG_HZ定义为多少,用户态USER_HZ都保持不变。

USER_HZ可以通过getconf CLK_TCK:100获得。

如/proc/stat中的jiffies,就是用户jiffies,按照10ms一次计算。