Linux 0.11启动时间的计算函数
Linux 0.11启动时间的计算函数
main.c下时间初始化代码,可以体会到位运算的精简
- #define CMOS_READ(addr) ({ \
- outb_p(0x80|addr,0x70); \
- inb_p(0x71); \
- })
- #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
- static void time_init(void)
- {
- struct tm time;
- do {
- time.tm_sec = CMOS_READ(0);
- time.tm_min = CMOS_READ(2);
- time.tm_hour = CMOS_READ(4);
- time.tm_mday = CMOS_READ(7);
- time.tm_mon = CMOS_READ(8);
- time.tm_year = CMOS_READ(9);
- } while (time.tm_sec != CMOS_READ(0));
- BCD_TO_BIN(time.tm_sec);
- BCD_TO_BIN(time.tm_min);
- BCD_TO_BIN(time.tm_hour);
- BCD_TO_BIN(time.tm_mday);
- BCD_TO_BIN(time.tm_mon);
- BCD_TO_BIN(time.tm_year);
- time.tm_mon--;
- startup_time = kernel_mktime(&time);
- }
kernel/mktime.c代码,其中包含了闰年的计算,但是代码确实那么精简,这就是算法和思想
闰年的基本计算方法是:
如果 y 能被 4 除尽且不能被 100 除尽,或者能被 400 除尽,则 y 是闰年。
- /*
- * linux/kernel/mktime.c
- *
- * (C) 1991 Linus Torvalds
- */
- #include <time.h>
- /*
- * This isn't the library routine, it is only used in the kernel.
- * as such, we don't care about years<1970 etc, but assume everything
- * is ok. Similarly, TZ etc is happily ignored. We just do everything
- * as easily as possible. Let's find something public for the library
- * routines (although I think minix times is public).
- */
- /*
- * PS. I hate whoever though up the year 1970 - couldn't they have gotten
- * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy.
- */
- #define MINUTE 60
- #define HOUR (60*MINUTE)
- #define DAY (24*HOUR)
- #define YEAR (365*DAY)
- /* interestingly, we assume leap-years */
- static int month[12] = {
- 0,
- DAY*(31),
- DAY*(31+29),
- DAY*(31+29+31),
- DAY*(31+29+31+30),
- DAY*(31+29+31+30+31),
- DAY*(31+29+31+30+31+30),
- DAY*(31+29+31+30+31+30+31),
- DAY*(31+29+31+30+31+30+31+31),
- DAY*(31+29+31+30+31+30+31+31+30),
- DAY*(31+29+31+30+31+30+31+31+30+31),
- DAY*(31+29+31+30+31+30+31+31+30+31+30)
- };
- long kernel_mktime(struct tm * tm)
- {
- long res;
- int year;
- year = tm->tm_year - 70;
- /* magic offsets (y+1) needed to get leapyears right.*/
- res = YEAR*year + DAY*((year+1)/4);
- res += month[tm->tm_mon];
- /* and (y+2) here. If it wasn't a leap-year, we have to adjust */
- if (tm->tm_mon>1 && ((year+2)%4))
- res -= DAY;
- res += DAY*(tm->tm_mday-1);
- res += HOUR*tm->tm_hour;
- res += MINUTE*tm->tm_min;
- res += tm->tm_sec;
- return res;
- }
评论暂时关闭