that carries on a CPU-intensive task often releases the CPU after a given amount of time. It will continue its
job when it is rescheduled for execution. This is especially important in kernel code, even though the kernel
supports kernel preemption. A common example in the networking code is given by the routines that
implement garbage collection.
expirations of the timer interrupt. The timer takes care of different tasks (we are not interested in them here)
and regularly expires HZ times per second. HZ is a variable initialized by architecture-dependent code. For
example, it is initialized to 1,000 on i386 machines. This means that the timer interrupt expires 1,000 times
per second when Linux runs on an i386 system, and that there is one millisecond between two consecutive
expirations.
Every time the timer expires it increments the global variable called jiffies. This means that at any time,
jiffies represents the number of ticks since the system booted, and the generic value n*HZ represents nseconds of time.
If all a function needs is to measure the passing of time, it can save the value of jiffies into a local
variable and later compare the difference between jiffies and that timestamp against a time interval(expressed in number of ticks) to see how much time has passed since measurement started.
The following example shows a function that needs to do some kind of work but does not want to hold the
CPU for more than one tick. When do_something says the work is completed by setting job_done to a
nonzero value, the function can return:
unsigned long start_time = jiffies;
int job_done = 0;do {
do_something(&job_done);
If (job_done)
return;
while (jiffies - start_time < 1);
Comparing Times
To compare the temporal relation of events, the kernel provides several auxiliary functions that prevent
off-by-one errors if they are used instead of a home-grown comparisons (a, b, and c denote jiffie time
values for some events):
❑ timer_after(a,b) returns true if time a is after time b. time_before(a,b) will be true if time a
is before time b, as you will have guessed.
❑ time_after_eq(a,b) works like time_after, but also returns true if both times are identical.
time_before_eq(a,b) is the inverse variant.
❑ time_in_range(a,b,c) checks if time a is contained in the time interval denoted by [b, c]. The
boundaries are included in the range, so a may be identical to b or c.
Using these functions ensures that wraparounds of the jiffies counter are handled correctly. As a general
rule, kernel code should therefore never compare time values directly, but always use these functions.
Time Conversion
When it comes to time intervals, jiffies might not be the unit of choice in the minds of most programmers.
It is more conventional to think in milliseconds or microseconds for short time intervals. The kernel thus
provides some auxiliary functions to convert back and forth between these units and jiffies:
<jiffies.h>
unsigned int jiffies_to_msecs(const unsigned long j);
unsigned int jiffies_to_usecs(const unsigned long j);
unsigned long msecs_to_jiffies(const unsigned int m);
unsigned long usecs_to_jiffies(const unsigned int u);
The functions are self-explanatory. However, Section 15.2.3 shows that conversion functions between
jiffies and struct timeval and struct timespec, respectively, are also available.
本文详细介绍了内核中时间测量的原理,包括使用ticks作为时间单位,以及如何通过jiffies变量记录时间。此外,文章还阐述了如何在内核代码中比较时间,以及时间单位之间的相互转换。
750

被折叠的 条评论
为什么被折叠?



