Next Previous Contents

2. Basic Timekeeping under Linux

A Linux system actually has two clocks: One is the battery powered "Real Time Clock" (also known as the "RTC", "CMOS clock", or "Hardware clock") which keeps track of time when the system is turned off but is not used when the system is running. The other is the "system clock" (sometimes called the "kernel clock" or "software clock") which is a software counter based on the timer interrupt. It does not exist when the system is not running, so it has to be initialized from the RTC (or some other time source) at boot time. References to "the clock" in the ntpd documentation refer to the system clock, not the RTC.

The two clocks will drift at different rates, so they will gradually drift apart from each other, and also away from the "real" time. The simplest way to keep them on time is to measure their drift rates and apply correction factors in software. Since the RTC is only used when the system is not running, the correction factor is applied when the clock is read at boot time, using clock(8) or hwclock(8). The system clock is corrected by adjusting the rate at which the system time is advanced with each timer interrupt, using adjtimex(8).

A crude alternative to adjtimex(8) is to have chron run clock(8) or hwclock(8) periodically to sync the system time to the (corrected) RTC. This was recommended in the clock(8) man page, and it works if you do it often enough that you don't cause large "jumps" in the system time, but adjtimex(8) is a more elegant solution. Some applications may complain if the time jumps backwards.

The next step up in accuracy is to use a program like ntpd to read the time periodically from a network time server or radio clock, and continuously adjust the rate of the system clock so that the times always match. If you always have a network connection at boot time, you can ignore the RTC completely and use ntpdate (which comes with the ntpd package) to initialize the system clock from the time server-- either a local server on a LAN, or a remote server on the internet. But if you sometimes don't have a network connection, or if you need the time to be accurate during the boot sequence before the network is active, then you need to maintain the time in the RTC as well.

It might seem obvious that in this case you would want to sync the RTC to the (corrected) system clock. But this turns out to be a bad idea if the system is going to stay shut down longer than a few minutes, because it interferes with the programs that apply the correction factor to the RTC at boot time.

If the system runs 24/7 and is always rebooted immediately whenever it's shut down, then you can just set the RTC from the system clock right before you reboot. The RTC won't drift enough to make a difference in the time it takes to reboot, so you don't have to know its drift rate.

Of course the system may go down unexpectedly, so some versions of the kernel sync the RTC to the system clock every 11 minutes if the system clock has been adjusted by another program. The RTC won't drift enough in 11 minutes to make any difference, but if the system is down long enough for the RTC to drift significantly, then you have a problem: the programs that apply the drift correction to the RTC need to know *exactly* when it was last reset, and the kernel doesn't record that information anywhere.

Some unix "traditionalists" might wonder why anyone would run a linux system less than 24/7, but some of us run dual-boot systems with another OS running some of the time, or run Linux on laptops that have to be shut down to conserve battery power when they're not being used. Other people just don't like to leave machines running unattended for long periods of time (even though we've heard all the arguments in favor of it). So, the "every 11 minutes" feature becomes a bug.

This "feature/bug" appears to behave differently in different versions of the kernel (and possibly in different versions of xntpd and ntpd as well), so if you're running both ntpd and hwclock you may need to test your system to see what it actually does. If you can't keep the kernel from resetting the RTC, you might have to run without a correction factor.

The part of the kernel that controls this can be found in /usr/src/linux-2.0.34/arch/i386/kernel/time.c (where the version number in the path will be the version of the kernel you're running). If the variable time_status is set to TIME_OK then the kernel will write the system time to the RTC every 11 minutes, otherwise it leaves the RTC alone. Calls to adjtimex(2) (as used by ntpd and timed, for example) may turn this on. Calls to settimeofday(2) will set time_status to TIME_UNSYNC, which tells the kernel not to adjust the RTC. I have not found any real documentation on this.

If you don't need sub-second accuracy, hwclock(8) and adjtimex(8) may be all you need. It's easy to get enthused about radio clocks and such, but I ran the old clock(8) program for years with excellent results. On the other hand, if you have several machines on a LAN it can be handy to have them automatically sync their clocks to each other.


Next Previous Contents