硬件時鐘。當(dāng)操作系統(tǒng)關(guān)機(jī)的時候,用這個來記錄時間,但是對于運行的系統(tǒng)是不用這個時間的。
另一個時間是 “System clock”也叫內(nèi)核時鐘或者軟件時鐘,是由軟件根據(jù)時間中斷來進(jìn)行計數(shù)的,
內(nèi)核時鐘在系統(tǒng)關(guān)機(jī)的情況下是不存在的,所以,當(dāng)操作系統(tǒng)啟動的時候,內(nèi)核時鐘是要讀取RTC時間
來進(jìn)行時間同步。并且在系統(tǒng)關(guān)機(jī)的時候?qū)⑾到y(tǒng)時間寫回RTC中進(jìn)行同步。
1) 內(nèi)核在啟動時從RTC中讀取啟動時的時間與日期;
2) 內(nèi)核在需要時將時間與日期回寫到RTC中。
The current time of day (the wall time) is defined in kernel/timer.c:
struct timespec xtime;
The timespec data structure is defined in
??????? time_t tv_sec;?????????????? /* seconds */
??????? long tv_nsec;??????????????? /* nanoseconds */
};
問題1:系統(tǒng)啟動時在哪讀取RTC的值并設(shè)置內(nèi)核時鐘進(jìn)行時間同步的呢?
最有可能讀取RTC設(shè)置內(nèi)核時鐘的位置應(yīng)該在arch/arm/kernel/time.c里的time_init函數(shù)內(nèi).
{
?if (system_timer->offset == NULL)
??system_timer->offset = dummy_gettimeoffset;
?system_timer->init();
?if (system_timer->dyn_tick)
??system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;
#endif
}
/* arch/cris/kernel/time.c */
/* grab the time from the RTC chip */
//讀RTC的函數(shù)
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
day = CMOS_READ(RTC_DAY_OF_MONTH);
mon = CMOS_READ(RTC_MONTH);
…………
return mktime(year, mon, day, hour, min, sec);
}
void update_xtime_from_cmos(void)
{
if(have_rtc) {
? xtime.tv_sec = get_cmos_time();
? xtime.tv_nsec = 0;
}
}
int set_rtc_mmss(unsigned long nowtime); /* write time into RTC chip */
ARM平臺啟動時并不走這邊.因此執(zhí)行不到這些函數(shù)。
那ARM平臺啟動時,系統(tǒng)是在哪讀RTC的值并對內(nèi)核時鐘(WallTime)進(jìn)行初始化的呢?
嵌入式Linux內(nèi)核(ARM)是在系統(tǒng)啟動時執(zhí)行/etc/init.d/hwclock.sh腳本,這個腳本會調(diào)用hwclock小程序讀取RTC的值并設(shè)置系統(tǒng)時鐘。
(換句話說,這要取決于你制作的文件系統(tǒng)里是否有這樣的腳本)
/* /etc/init.d/hwclock.sh */
start() {
??? local RET ERROR=
??? log_status_msg "Setting the System Clock using the Hardware Clock as reference..." -n
??? # timezone for hardware clocks in local time, and sets kernel
??? # timezone. DO NOT REMOVE.
??? [ "$HWCLOCKACCESS" != no ] && $DAEMON1 --hctosys $GMT $BADYEAR
??? # Now that /usr/share/zoneinfo should be available,
??? # announce the local time.
??? #
??? log_status_msg "System Clock set. Local time: `date`"
??? log_status_msg ""
??? return 0
}
hwclock最先讀取的設(shè)備文件是 /dev/rtc? ,busybox里面的hwclock是這樣實現(xiàn)的:
static int xopen_rtc(int flags)
{
?int rtc;
??rtc = open("/dev/rtc", flags);
??if (rtc >= 0)
???return rtc;
??rtc = open("/dev/rtc0", flags);
??if (rtc >= 0)
???return rtc;
??rtcname = "/dev/misc/rtc";
?}
?return xopen(rtcname, flags);
}
通過set_rtc函數(shù)指針指向的函數(shù),set_rtc在arch/arm/kernel/time.c內(nèi)
/* arch/arm/kernel/time.c */
/*
?* hook for setting the RTC's idea of the current time.
?*/
int (*set_rtc)(void);
set_rtc在do_set_rtc內(nèi)調(diào)用
static inline void do_set_rtc(void)
{
?……
?if (set_rtc())
??/*
?? * rtc update failed.? Try again in 60s
?? */
??next_rtc_update = xtime.tv_sec + 60;
?else
??next_rtc_update = xtime.tv_sec + 660;?/* update every ~11 minutes by default*/
}
/*
?* Kernel system timer support.?
?*/
void timer_tick(struct pt_regs *regs)
{
?profile_tick(CPU_PROFILING, regs);
?do_leds();
?do_set_rtc();
?do_timer(1);
?……
}
timer_tick為Kernel提供的體系架構(gòu)無關(guān)的時鐘中斷處理函數(shù),通常會在體系架構(gòu)相關(guān)的時鐘中斷處理函數(shù)內(nèi)調(diào)用它。如s3c2410是這樣的:
?* IRQ handler for the timer
?*/
static irqreturn_t
s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
?write_seqlock(&xtime_lock);
?timer_tick(regs);
?write_sequnlock(&xtime_lock);
?return IRQ_HANDLED;
}
評論