1. Timer interrupts
The Linux Kernel uses timer interrupts(定时器中断) to track the passage of time.
Timer interruptsare periodically generated by timer hardware.
--- like the swinging of a pendulum(钟摆) in a clock, timer interrupts are repetitious(重复的) events with a consistent frequency.
--- unlike a pendulum, the frequency of the interrupts can be programmed.
The kernel tracks time by counting timer interrupts.
2. HZ --- constant representing the number of timer interrupts per second.
Timer interrupt frequency is programmed by the linux kernel at boot time, using a parameter calledHZ.
the value of HZ is parameter which can be configured when you build your kernel.
It's defined in <asm/param.h>
#ifdef __KERNEL__
# define HZ CONFIG_HZ /* Internal kernel timer frequency */
# define USER_HZ 100 /* User interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#else
# define HZ 100
#endif
3. The jiffy(时间段)
a jiffy is the amount of time which elapses between timer interrupts.
Most folks use the term jiffy to mean a short period of time, but in Linux, a jiffy is mathematically described as: 1 jiffy = 1/HZ second.
3.1 jiffies and jiffies_64
to track time, the kernel maintains a counter which counts the number of jiffies that has elapsed since the system started.
each time the kernel sees a timer interrupt, it increments this counter.
--- when the counter hits it's maximum value, it simply wraps back around to zero.
the value of this counter is accessible to drivers via 2 variables:
--- the full 64-bits are available using jiffies_64.
--- low 32-bits are available using jiffies.
4. using jiffies:
get_jiffies_64(); --- provides atomic access to jiffies_64 on all architectures.
4.1 summary of API to compare jiffies values:
time_after(a, b); --- true if time a is after time b.
time_after_eq(a, b); --- true if time a is the same, or after time b.
time_before_eq(a, b ); --- true if time a is the same, or before time b.
time_before(a, b); --- true if time a is before time b.
time_in_range(a, b, c); --- return true if time a is between the range defined by time b and time c.
compare a value(32-bit only) of jiffies to the current time counter value.
time_is_after_jiffies(a); --- true is time a is after to the current counter value.
time_is_after_eq_jiffies(a); --- true is time a is the same, or after to the current counter value.
time_is_before_eq_jiffies(a); --- true is time a is the same, or before to the current counter value.
time_is_before_jiffies(a); --- true is time a is before to the current counter value.
for jiffies64 :
time_after64(a, b); --- true if time a is after time b.
time_after_eq64(a, b); --- true if time a is the same, or after time b.
time_before_eq64(a, b ); --- true if time a is the same, or before time b.
time_before64(a, b); --- true if time a is before time b.
4.2 Summary of API relating to converting jiffies values:
jiffies_to_msecs(a); --- convert between jiffies to milliseconds.
msecs_to_jiffies(a);
jiffies_to_usecs(a); --- convert between jiffies to microseconds.
usecs_to_jiffies(a);
convert between jiffies and struct timespec, commonly used in linux user-space:
struct timespec {
__kernel_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
jiffies_to_timespec(a, tb); --- convert time a to struct timespec, storing result at tb. tb is a timespec struct.
timespec_to_jiffies(ta); --- convert timespec ta to jiffies. return jiffies. ta is a times
convert between jiffies and struct timeval. (oder but still commonly used in linux user-space):
struct timeval {
__kernel_time_t tv_sec; /* seconds */
__kernel_suseconds_t tv_usec; /* microseconds */
};
jiffies_to_timeval(a, tb); //convert time a to struct timeval tb. storing result at tb.
timeval_to_jiffies(a); //convert struct timeval a to jiffies.