开机启动时间是大部分与时间相关的计算的基础。操作系统中一些程序的运算需要时间参数;很多事务的处理也都要用到时间,比如文件修改的时间、文件最近访问的时间、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所示。
相关资源:七夕情人节表白HTML源码(两款)