NetBSD-1.0 时间设置的一个bug

    每次使用 date 命令设置主机时间,再次重启后时间就和设置的不一样了!查看启动时的日志:

技术分享

对应的代码为 arch/i386/isa/clock.c 的 startrtclock 函数:

        /* Check diagnostic status */
        outb (IO_RTC, RTC_DIAG);
    if (s = inb (IO_RTC+1))
        printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);

为什么 RTC 的诊断状态会不对呢?

经过调试和更高版本的NetBSD代码比对之后,发现问题的原因为同一个文件里的 resettodr 函数:

    rtclk.rtc_min = dectohexdec(n%60);
    rtclk.rtc_hr = dectohexdec(n/60);

    n = (time.tv_sec - diff) / (3600 * 24);    /* days */
    rtclk.rtc_dow = (n + 4) % 7;  /* 1/1/70 is Thursday */

    for (j = 1970, i = yeartoday(j); n >= i; j++, i = yeartoday(j))
        n -= i;

    rtclk.rtc_yr = dectohexdec(j - 1900);

    if (i == 366)
        month[1] = 29;
    for (i = 0; n >= month[i]; i++)
        n -= month[i];
    month[1] = 28;
    rtclk.rtc_mon = dectohexdec(++i);

    rtclk.rtc_dom = dectohexdec(++n);

红色粗体部分,直接设置年份为当前年份和 1900 年的差值。但是从 RTC 读取的时候,却又是:

    sec = hexdectodec(rtclk.rtc_sec);
    min = hexdectodec(rtclk.rtc_min);
    hr = hexdectodec(rtclk.rtc_hr);
    dom = hexdectodec(rtclk.rtc_dom);
    mon = hexdectodec(rtclk.rtc_mon);
    yr = hexdectodec(rtclk.rtc_yr);
    yr = (yr < 70) ? yr+100 : yr;

    n = sec + 60 * min + 3600 * hr;
    n += (dom - 1) * 3600 * 24;

    if (yeartoday(yr) == 366)
        month[1] = 29;

保存在 RTC 里的年份数值只是实际年份的后两位,所以修改代码为:

    rtclk.rtc_min = dectohexdec(n%60);
    rtclk.rtc_hr = dectohexdec(n/60);

    n = (time.tv_sec - diff) / (3600 * 24);    /* days */
    rtclk.rtc_dow = (n + 4) % 7;  /* 1/1/70 is Thursday */

    for (j = 1970, i = yeartoday(j); n >= i; j++, i = yeartoday(j))
        n -= i;

    rtclk.rtc_yr = dectohexdec( ( j - 1900 ) % 100 );

    if (i == 366)
        month[1] = 29;
    for (i = 0; n >= month[i]; i++)
        n -= month[i];
    month[1] = 28;
    rtclk.rtc_mon = dectohexdec(++i);

    rtclk.rtc_dom = dectohexdec(++n);

重编译并更新内核之后,问题解决。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。