Skip to content

16 时间初始化time init:操作系统怎么获取当前时间?

你好,我是闪客。

上一讲咱们说到,通过初始化控制台的 tty_init 操作,内核代码已经可以很方便地在控制台输出字符啦!

用户也可以通过敲击键盘,或调用诸如 printf 这样的库函数,在屏幕上输出信息,或使用换行和滚屏等功能。这些都得益于 tty_init 这个初始化方法和它对外封装的小功能函数在底层的支撑。

时间初始化 time_init

我们继续看下一个初始化的倒霉鬼,time_init

// init/main.c
void main(void) {
    ...
    time_init();
    ...
}

曾经我很好奇,操作系统是怎么获取到当前时间的呢

当然,现在都联网了,它可以从网络上实时同步时间。但没有网络时,为什么操作系统启动之后可以显示出当前的时间呢?难道操作系统在电脑关机后,依然不停地在某处运行着,勤勤恳恳地数着秒表么?

当然不是,我们今天就打开这个 time_init 函数一探究竟。

打开这个函数后我又是很开心,因为它很短,且没有更深入的方法调用。

// init/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);
}