Arch Linux 与 Windows 11 双系统时间问题的解决

前言

重装 Arch + Windows 双系统后,我发现每当切换系统时,系统的时间总是会出现偏差。

Arch 下倒还好,系统会很快自动纠正好时间。但是我们非常好用的 Windows 系统却非常随机——纠不纠正、什么时候纠正都相当的随性,很多时候我都需要自己打开设置手动校准。

经过观察,我发现一个规律:两个系统之间的时间差很巧妙的是 8 个小时——正好是 UTC 时间与北京时间之间的时差,因此我猜测这可能与 Windows 和 Linux 对待 本地时间UTC 时间 的机制有关。

在这篇知乎文章里,我找到了问题所在和解决方案。

问题

Windows 采用的是 LocalTime 机制,直接将从 BIOS 中存储的时间视为本地时间,而 Arch Linux 则将 BIOS 中的时间视为 UTC 时间

而且,在写入硬件时间时,Windows 直接把从网络同步的时间写入 BIOS,但是Arch Linux 则将网络时间减去时间偏移(对北京时间来说就是8小时),这就造成了两个系统时间的不一致。

解决方案

按照这篇文章,我们先安装 ntpdate 工具:

1
2
# 使用 yay 安装
$ yay -S ntpdate

经过漫长的编译……BOOM!

1
2
3
4
5
==> 错误: 在 build() 中发生一个错误。
正在放弃...
-> 生成时出错: ntpdate-exit status 4
-> 无法安装以下软件包, 需要手动介入处理:
ntpdate - exit status 4

嘛,用 Arch Linux 也有一段时间了,对这种情况我已经见怪不怪了,往上翻翻,gcc 的报错信息这么提醒我们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ntp_control.c: 在函数‘derive_nonce’中:
ntp_control.c:3667:25: 错误:传递‘MD5Update’的第 2 个参数时在不兼容的指针类型间转换 [-Wincompatible-pointer-types]
3667 | MD5Update(&ctx, salt, sizeof(salt));
| ^~~~
| |
| u_int32 * {或称 unsigned int *}
包含于文件 ../include/ntp_md5.h:11,
于 ../include/ntp_stdlib.h:15,
于 ../include/ntp.h:13,
于 ../include/ntpd.h:11,
于 ntp_control.c:19:
/usr/include/md5.h:37:31: 附注:需要类型‘const uint8_t *’ {或称 ‘const unsigned char *’},但实参的类型为‘u_int32 *’ {或称 ‘unsigned int *’}
37 | void MD5Update(MD5_CTX *, const uint8_t *, size_t);
| ^~~~~~~~~~~~~~~
ntp_control.c:3668:25: 错误:传递‘MD5Update’的第 2 个参数时在不兼容的指针类型间转换 [-Wincompatible-pointer-types]
3668 | MD5Update(&ctx, &ts_i, sizeof(ts_i));
| ^~~~~
| |
| u_int32 * {或称 unsigned int *}

关键的信息便是 传递‘MD5Update’的第 2 个参数时在不兼容的指针类型间转换 [-Wincompatible-pointer-types],看起来似乎是在调用 MD5Update 函数时,传递了不兼容的指针类型

ntpdate 包的 AUR 页面下,也有人提到了这个问题,并给出了解决方案:更改 ntpdate 包的 PKGBUILD 文件,在 build() 块中添加 CFLAGS="${CFLAGS} -Wno-incompatible-pointer-types" ,再重新构建即可。

方案已经给出,那就试试看吧!首先先查看本地缓存的 ntpdate 有关文件:

1
2
3
4
$ cd ~/.cache/yay/ntpdate/
$ ls
pkg bug_3926_pthread_detach.patch ntpdate.conf PKGBUILD
src ntp-4.2.8p18.tar.gz ntpdate.service

接下来,编辑 PKGBUILD 文件:

1
$ vim PKGBUILD

更改 build() 块:

1
2
3
4
5
6
build() {
CFLAGS="${CFLAGS} -Wno-incompatible-pointer-types" # 添加这一行
cd "${srcdir}/${_pkgname}-${_pkgver}"
./configure --prefix=/usr --libexecdir=/usr/lib
make
}

保存并退出,然后重新构建 ntpdate 包:

1
$ makepkg -i -c

这下就成功通过编译并安装了!

下一步,使用 ntpdate 同步时间:

1
$ sudo ntpdate time.windows.com

最后,使用 hwclock 命令将硬件时间配置为本地时间——和 Windows 保持一致。

1
$ sudo hwclock --systohc --localtime

完成!至此,两个系统间的时间应该就能保持一致了,可以重启检验一下。