7.2. Learn the current time
The kernel code can always get a representation of the current time by viewing the value of the jifies. Often, this value represents only the time since the last boot, and this fact is irrelevant to the driver because its lifecycle is limited by the uptime of the system. As shown, the driver can use the current value of jiffies to calculate the time interval between events (for example, to differentiate from single hits in input drivers or to compute timeouts). Simply speaking, viewing jiffies is almost always enough when you need to measure time intervals. If you need very precise measurements of a short time loss, processor-specific registers help (although they pose a serious portability problem).
It is very unlikely that a driver would need to know the wall clock time, to months, days, and hours to express; This information is often only required for user programs, such as Cron and syslogd. The time to deal with the real world is often best left to the user space, where the C library provides better support; In addition, such code is often too strategically relevant to be part of the kernel. There is a kernel function that transforms a wall clock time to a jiffies value, but:
#include <linux/time.h>
unsigned long mktime (unsigned int, unsigned int mon,
unsigned int day, Unsigne d int hour,
unsigned int min, unsigned int sec);
Repetition: Handling the wall clock time directly in the drive is often a signal to implement the strategy and should therefore be questioned.
Although you will not necessarily handle human readable time representations, sometimes you need to even process absolute time in kernel space. To do this, <linux/time.h> outputs the Do_gettimeofday function. When invoked, it populates a struct timeval pointer-the same as used in Gettimeofday system calls-using similar seconds and millisecond values. Do_gettimeofday's prototype is:
#include <linux/time.h>
void do_gettimeofday (struct timeval *tv);
This source code declares that Do_gettimeofday has "near-millisecond precision" because it asks how much of the current Jiffy ratio has been lost. This precision is different for each system, however, because it relies on the hardware mechanism in use in practice. For example, some M68KNOMMU processors, SUN3 systems, and other m68k systems cannot provide precision greater than jiffy. The Pentium system, on the other hand, provides very fast and accurate measurements smaller than the tick, by reading the timestamp counter described earlier in this chapter.
The current time is also available (although using Jiffy granularity) comes from the xtime variable, a struct TIMESPEC value. This variable is not encouraged to be used directly because it is difficult to access these 2 fields simultaneously. Therefore, the kernel provides a utility function Current_kernel_time:
#include <linux/time.h>
struct timespec current_kernel_time (void);
The code used in various ways to obtain the current time can be obtained from the JIT ("just In Time") module of the source file on the FTP Web site provided by O ' Reilly. JIT creates a file called/proc/currentime, which, when read, returns the following entries in ASCII code:
The current jiffies and jiffies_64 values, in the form of a 16 binary number.
The same current time as the Do_gettimeofday returned.
The Timespec returned by Current_kernel_time.
We chose to use a dynamic/proc file to keep the boilerplate code to a minimum-it's not worth creating an entire device just to return a bit of textual information.
This file continuously returns lines of text as long as the module is loaded; Each read system call collects and returns a set of data that is organized into 2 rows for better reading. Whenever you read multiple datasets in less than one clock, you'll see the difference between do_gettimeofday, which asks for hardware, and other values are updated only when the clock ticks.
phon% head-8/proc/currentime
0x00bdbc1f 0x0000000100bdbc1f 1062370899.630126
0x00bdbc1f 0x0000000100bdbc1f 1062370899.630150
1062370899.629161488
0x00bdbc20 0x0000000100bdbc20 1062370899.630208
1062370899.630161336
0x00bdbc20 0x0000000100bdbc20 1062370899.630233
1062370899.630161336
In the screenshot above, there are 2 interesting things to watch out for. First of all, this current_kernel_time value, although expressed in nanoseconds, only the tick size of the clock; Do_gettimeofday continues to report a later time but not later than the next clock tick. Second, this 64-bit jiffies counter has the least significant bit of a high 32-bit word set. This is due to the default value of the Initial_jiffies, which is used to initialize the counter at startup time, imposing a low word overflow within a few minutes of startup time to help detect problems associated with this overflow. This initialization preference in the counter has no effect because the jiffies has nothing to do with clock time on the wall. In/proc/uptime, where the kernel extracts uptime from the counter, initialization preferences are removed before conversion.
1, using the RTC device, this clock can be used in various modes
2, reference system call Adjtimex
This is the second way to use
System Call Adjtimex
Keep going, you'll find the last call
void Do_gettimeofday (struct timeval *tv)
Then direct use of do_gettimeofday can get struct timeval
struct Timeval {
time_t tv_sec; * Seconds * *
suseconds_t tv_usec; * Microseconds * *
};
Then it is necessary to convert this tv_sec, the number of seconds since 1970, to the date of the month.
In fact, the kernel already has such a function
/*
* Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
*/
void Rtc_time_to_tm (unsigned long time, struct rtc_time *tm)
The only disadvantage is that the conversion is obtained in UTC time, with a 8 hour lag from Beijing. To achieve the effect of User state localtime (), you must obtain the time zone information in/etc/localtime.
Sample code:
#include <linux/timer.h>
#include <linux/timex.h>
#include <linux/rtc.h>
/ * Add to the appropriate location * *
struct Timex Txc;
struct Rtc_time TM;
Do_gettimeofday (& (Txc.time));
Rtc_time_to_tm (TXC.TIME.TV_SEC,&TM);
PRINTK ("UTC Time:%d-%d-%d%d:%d:%d/n", Tm.tm_year+1900,tm.tm_mon, tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);