硬件時(shí)鐘。當(dāng)操作系統(tǒng)關(guān)機(jī)的時(shí)候,用這個(gè)來(lái)記錄時(shí)間,但是對(duì)于運(yùn)行的系統(tǒng)是不用這個(gè)時(shí)間的。
另一個(gè)時(shí)間是 “System clock”也叫內(nèi)核時(shí)鐘或者軟件時(shí)鐘,是由軟件根據(jù)時(shí)間中斷來(lái)進(jìn)行計(jì)數(shù)的,
內(nèi)核時(shí)鐘在系統(tǒng)關(guān)機(jī)的情況下是不存在的,所以,當(dāng)操作系統(tǒng)啟動(dòng)的時(shí)候,內(nèi)核時(shí)鐘是要讀取RTC時(shí)間
來(lái)進(jìn)行時(shí)間同步。并且在系統(tǒng)關(guān)機(jī)的時(shí)候?qū)⑾到y(tǒng)時(shí)間寫(xiě)回RTC中進(jìn)行同步。
1) 內(nèi)核在啟動(dòng)時(shí)從RTC中讀取啟動(dòng)時(shí)的時(shí)間與日期;
2) 內(nèi)核在需要時(shí)將時(shí)間與日期回寫(xiě)到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 */
};
問(wèn)題1:系統(tǒng)啟動(dòng)時(shí)在哪讀取RTC的值并設(shè)置內(nèi)核時(shí)鐘進(jìn)行時(shí)間同步的呢?
最有可能讀取RTC設(shè)置內(nèi)核時(shí)鐘的位置應(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平臺(tái)啟動(dòng)時(shí)并不走這邊.因此執(zhí)行不到這些函數(shù)。
那ARM平臺(tái)啟動(dòng)時(shí),系統(tǒng)是在哪讀RTC的值并對(duì)內(nèi)核時(shí)鐘(WallTime)進(jìn)行初始化的呢?
嵌入式Linux內(nèi)核(ARM)是在系統(tǒng)啟動(dòng)時(shí)執(zhí)行/etc/init.d/hwclock.sh腳本,這個(gè)腳本會(huì)調(diào)用hwclock小程序讀取RTC的值并設(shè)置系統(tǒng)時(shí)鐘。
(換句話說(shuō),這要取決于你制作的文件系統(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是這樣實(shí)現(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);
}
通過(guò)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)無(wú)關(guān)的時(shí)鐘中斷處理函數(shù),通常會(huì)在體系架構(gòu)相關(guān)的時(shí)鐘中斷處理函數(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;
}
評(píng)論