2.8 开机启动时间设置
开机启动时间是大部分与时间相关的计算的基础。操作系统中一些程序的运算需要时间参数;很多事务的处理也都要用到时间,比如文件修改的时间、文件最近访问的时间、i节点自身的修改时间等。有了开机启动时间,其他时间就可据此推算出来。
具体执行步骤是:CMOS是主板上的一个小存储芯片,系统通过调用time_init()函数,先对它上面记录的时间数据进行采集,提取不同等级的时间要素,比如秒(time.tm_sec)、分(time.tm_min)、年(time.tm_year)等,然后对这些要素进行整合,并最终得出开机启动时间(startup_time)。
执行代码如下:
//代码路径:init/main.c:
void main(void)
{
…
time_init();
…
}
#define CMOS_READ(addr) ({ \ //读CMOS实时时钟信息
outb_p(0x80|addr,0x70); \ //0x80|addr读CMOS地址,0x70写端口
inb_p(0x71); \ //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); //开机时间,从1970年1月1日0时计算
}
//代码路径:include\asm\io.h: //嵌入汇编参看trap_init的注释
#define outb_p(value,port) \ //将value写到port
__asm__ ("outb %%al,%%dx\n" \
"\tjmp 1f\n" \ //jmp到下面的第一个1:处,目的是延迟
"1:\tjmp 1f\n" \
"1:"::"a" (value),"d" (port))
#define inb_p(port) ({ \
unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al\n" \ // volatile,禁止编译器优化下列代码
"\tjmp 1f\n" \ //延迟
"1:\tjmp 1f\n" \
"1:":"=a" (_v):"d" (port)); \
_v; \
})
计算过程及开机启动时间在内存中的存储位置如图2-16所示。