Linux 0.11启动时间的计算函数


main.c下时间初始化代码,可以体会到位运算的精简

  1. #define CMOS_READ(addr) ({ \   
  2. outb_p(0x80|addr,0x70); \   
  3. inb_p(0x71); \   
  4. })   
  5. #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)   
  6. static void time_init(void)   
  7. {   
  8.     struct tm time;   
  9.     do {   
  10.         time.tm_sec = CMOS_READ(0);   
  11.         time.tm_min = CMOS_READ(2);   
  12.         time.tm_hour = CMOS_READ(4);   
  13.         time.tm_mday = CMOS_READ(7);   
  14.         time.tm_mon = CMOS_READ(8);   
  15.         time.tm_year = CMOS_READ(9);   
  16.     } while (time.tm_sec != CMOS_READ(0));   
  17.     BCD_TO_BIN(time.tm_sec);   
  18.     BCD_TO_BIN(time.tm_min);   
  19.     BCD_TO_BIN(time.tm_hour);   
  20.     BCD_TO_BIN(time.tm_mday);   
  21.     BCD_TO_BIN(time.tm_mon);   
  22.     BCD_TO_BIN(time.tm_year);   
  23.     time.tm_mon--;   
  24.     startup_time = kernel_mktime(&time);   
  25. }  

kernel/mktime.c代码,其中包含了闰年的计算,但是代码确实那么精简,这就是算法和思想

闰年的基本计算方法是:

如果 y 能被 4 除尽且不能被 100 除尽,或者能被 400 除尽,则 y 是闰年。

  1. /*  
  2.  *  linux/kernel/mktime.c  
  3.  *  
  4.  *  (C) 1991  Linus Torvalds  
  5.  */  
  6. #include <time.h>   
  7. /*  
  8.  * This isn't the library routine, it is only used in the kernel.  
  9.  * as such, we don't care about years<1970 etc, but assume everything  
  10.  * is ok. Similarly, TZ etc is happily ignored. We just do everything  
  11.  * as easily as possible. Let's find something public for the library  
  12.  * routines (although I think minix times is public).  
  13.  */  
  14. /*  
  15.  * PS. I hate whoever though up the year 1970 - couldn't they have gotten  
  16.  * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy.  
  17.  */  
  18. #define MINUTE 60   
  19. #define HOUR (60*MINUTE)   
  20. #define DAY (24*HOUR)   
  21. #define YEAR (365*DAY)   
  22. /* interestingly, we assume leap-years */  
  23. static int month[12] = {   
  24.     0,   
  25.     DAY*(31),   
  26.     DAY*(31+29),   
  27.     DAY*(31+29+31),   
  28.     DAY*(31+29+31+30),   
  29.     DAY*(31+29+31+30+31),   
  30.     DAY*(31+29+31+30+31+30),   
  31.     DAY*(31+29+31+30+31+30+31),   
  32.     DAY*(31+29+31+30+31+30+31+31),   
  33.     DAY*(31+29+31+30+31+30+31+31+30),   
  34.     DAY*(31+29+31+30+31+30+31+31+30+31),   
  35.     DAY*(31+29+31+30+31+30+31+31+30+31+30)   
  36. };   
  37. long kernel_mktime(struct tm * tm)   
  38. {   
  39.     long res;   
  40.     int year;   
  41.     year = tm->tm_year - 70;   
  42. /* magic offsets (y+1) needed to get leapyears right.*/  
  43.     res = YEAR*year + DAY*((year+1)/4);   
  44.     res += month[tm->tm_mon];   
  45. /* and (y+2) here. If it wasn't a leap-year, we have to adjust */  
  46.     if (tm->tm_mon>1 && ((year+2)%4))   
  47.         res -= DAY;   
  48.     res += DAY*(tm->tm_mday-1);   
  49.     res += HOUR*tm->tm_hour;   
  50.     res += MINUTE*tm->tm_min;   
  51.     res += tm->tm_sec;   
  52.     return res;   
  53. }  

相关内容