我发现了 lscpu 在旧版和新版的不同输出行为,为了验证我的猜想,我重新编译了 util-linux,这篇文章是对整个过程的记录
我近期开始学习 RHCA 课程,首门课程是 RH442。
我平时很少使用 Red Hat 及其衍生发行版,平时更是 Ubuntu 和 Debian 系最为常用。首先在课上发现了 lscpu 的输出与手边的 Ubuntu 22.04 和 Debian 11 大不相同。
这个问题尤其集中在缓存的大小显示上。
例如,在我笔记本的虚拟机中,AlmaLinux 8 显示的内容如下
1$ lscpu
2Architecture: x86_64
3CPU op-mode(s): 32-bit, 64-bit
4Byte Order: Little Endian
5CPU(s): 2
6On-line CPU(s) list: 0,1
7Thread(s) per core: 1
8Core(s) per socket: 1
9Socket(s): 2
10NUMA node(s): 1
11Vendor ID: GenuineIntel
12CPU family: 6
13Model: 158
14Model name: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
15Stepping: 10
16CPU MHz: 2208.000
17BogoMIPS: 4416.00
18Hypervisor vendor: VMware
19Virtualization type: full
20L1d cache: 32K
21L1i cache: 32K
22L2 cache: 256K
23L3 cache: 9216K
24NUMA node0 CPU(s): 0,1
25Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
注意此处的 L1 缓存和 L2 缓存为 32K+32K 以及 256K
而同样此电脑上的 Ubuntu 显示如下:
1$ lscpu
2Architecture: x86_64
3 CPU op-mode(s): 32-bit, 64-bit
4 Address sizes: 45 bits physical, 48 bits virtual
5 Byte Order: Little Endian
6CPU(s): 2
7 On-line CPU(s) list: 0,1
8Vendor ID: GenuineIntel
9 Model name: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
10 CPU family: 6
11 Model: 158
12 Thread(s) per core: 1
13 Core(s) per socket: 1
14 Socket(s): 2
15 Stepping: 10
16 BogoMIPS: 4416.00
17 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_t
18 sc cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault inv
19 pcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d a
20 rch_capabilities
21Virtualization features:
22 Virtualization: VT-x
23 Hypervisor vendor: VMware
24 Virtualization type: full
25Caches (sum of all):
26 L1d: 64 KiB (2 instances)
27 L1i: 64 KiB (2 instances)
28 L2: 512 KiB (2 instances)
29 L3: 18 MiB (2 instances)
30NUMA:
31 NUMA node(s): 1
32 NUMA node0 CPU(s): 0,1
33Vulnerabilities:
34 Itlb multihit: KVM: Mitigation: VMX disabled
35 L1tf: Mitigation; PTE Inversion; VMX flush not necessary, SMT disabled
36 Mds: Mitigation; Clear CPU buffers; SMT Host state unknown
37 Meltdown: Mitigation; PTI
38 Mmio stale data: Mitigation; Clear CPU buffers; SMT Host state unknown
39 Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
40 Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
41 Spectre v2: Mitigation; Retpolines, IBPB conditional, IBRS_FW, STIBP disabled, RSB filling
42 Srbds: Unknown: Dependent on hypervisor status
43 Tsx async abort: Not affected
可以看到,不但显示的内容多了许多,并且注意此处的 Cache 值,他是所有的核心缓存加在一起的值。
更加让人迷惑的,是 Debian 11 附带的 lscpu,他的显示效果如下。
1$ lscpu
2Architecture: x86_64
3CPU op-mode(s): 32-bit, 64-bit
4Byte Order: Little Endian
5CPU(s): 2
6On-line CPU(s) list: 0,1
7Thread(s) per core: 1
8Core(s) per socket: 1
9Socket(s): 2
10NUMA node(s): 1
11Vendor ID: GenuineIntel
12CPU family: 6
13Model: 158
14Model name: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
15Stepping: 10
16CPU MHz: 2208.000
17BogoMIPS: 4416.00
18Hypervisor vendor: VMware
19Virtualization type: full
20L1d cache: 32K
21L1i cache: 32K
22L2 cache: 256K
23L3 cache: 9216K
24NUMA node0 CPU(s): 0,1
25Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
此时表面上看起来,他和 AlmaLinux 中的结果差距不大,但此时的缓存是以所有缓存量相加在一起计算的,且不像 Ubuntu 22.04,他并没有注明是多个 instences 的值。这就更令人迷惑了。
我一开始认为,既然两种发行版的 lscpu 都来源于上游的 util-linux 包,他们不应该有这么大的差别,马上想到的是 Red Hat 这个 backport 狂魔用补丁改了行为。
因此我去翻看了来源 CentOS Stream 8 的 RPM 源码树,尽管确实有些与 lscpu 相关的 patch,但并不存在修改输出这种 patch。
从 util-linux 的编译选项中也看不出什么会影响输出的区别。
因此,只能猜测是由于版本不同,上游的包发生了 break change。
并且,三个系统的 util-linux 包版本确实各不相同:
1# AlmaLinux 8
2lscpu from util-linux 2.32.1
3# Debian 11
4lscpu from util-linux 2.36.1
5# Ubuntu 22.04
6lscpu from util-linux 2.37.2
为了验证猜测,我决定干脆来试试。
我选择只编译 2.32.1 和 2.36.1 两个版本。
util-linux 可以从 kernel.org 下载到上游打包好的源码包。
从网站上下载到 util-linux-2.32.1.tar.gz 和 util-linux-2.36.1.tar.xz 两个源码包并解压。
为了控制变量,我选择了在 AlmaLinux 环境下,使用 AlmaLinux RPM 包中的 configure 选项编译,并且不改变 CFLAGS 的值。
首先安装编译依赖。
由于编译依赖有许多,为了不影响我的环境,我选择使用一个 Docker 容器来编译。
1docker run -it -v `pwd`:/usr/src almalinux:8 bash
2
3# 进入容器内
4cd /usr/src
在安装依赖前,其中两个包需要启用 PowerTools 源
1dnf config-manager --set-enabled powertools
安装编译依赖,这些依赖都是从 SRPM 的 SPEC 文件中得来的。
1dnf install audit-libs-devel gettext-devel libselinux-devel ncurses-devel pam-devel zlib-devel popt-devel libutempter-devel systemd-devel systemd libuser-devel libcap-ng-devel python3-devel gcc automake autoconf libtool bison git-core make diffutils
接下来完成编译
1cd util-linux-2.32.1
2./autogen.sh
3
4./configure \
5 --disable-assert \
6 --with-systemdsystemunitdir=/usr/lib/systemd/system \
7 --disable-silent-rules \
8 --disable-bfs \
9 --disable-pg \
10 --enable-chfn-chsh \
11 --enable-usrdir-path \
12 --enable-write \
13 --enable-raw \
14 --with-python=3.6 \
15 --with-systemd \
16 --with-udev \
17 --with-selinux \
18 --with-audit \
19 --with-utempter \
20 --disable-makeinstall-chown
21
22make
2.36 版也使用相同方式编译。
编译之后,就可以在源码根目录得到我们所需要的 lscpu
二进制文件。在 AlmaLinux 环境中运行这两个版本的文件,得到了确实不同的结果。
1$ cat /etc/redhat-release
2AlmaLinux release 8.6 (Sky Tiger)
3$ ./util-linux-2.32.1/lscpu --version
4lt-lscpu from util-linux 2.32.1
5$ ./util-linux-2.32.1/lscpu
6Architecture: x86_64
7CPU op-mode(s): 32-bit, 64-bit
8Byte Order: Little Endian
9CPU(s): 2
10On-line CPU(s) list: 0,1
11Thread(s) per core: 1
12Core(s) per socket: 1
13Socket(s): 2
14NUMA node(s): 1
15Vendor ID: GenuineIntel
16CPU family: 6
17Model: 158
18Model name: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
19Stepping: 10
20CPU MHz: 2208.000
21BogoMIPS: 4416.00
22Hypervisor vendor: VMware
23Virtualization type: full
24L1d cache: 32K
25L1i cache: 32K
26L2 cache: 256K
27L3 cache: 9216K
28NUMA node0 CPU(s): 0,1
29Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
30$ ./util-linux-2.36.1/lscpu --version
31lscpu from util-linux 2.36.1
32$ ./util-linux-2.36.1/lscpu
33Architecture: x86_64
34CPU op-mode(s): 32-bit, 64-bit
35Byte Order: Little Endian
36Address sizes: 45 bits physical, 48 bits virtual
37CPU(s): 2
38On-line CPU(s) list: 0,1
39Thread(s) per core: 1
40Core(s) per socket: 1
41Socket(s): 2
42NUMA node(s): 1
43Vendor ID: GenuineIntel
44CPU family: 6
45Model: 158
46Model name: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
47Stepping: 10
48CPU MHz: 2208.000
49BogoMIPS: 4416.00
50Hypervisor vendor: VMware
51Virtualization type: full
52L1d cache: 64 KiB
53L1i cache: 64 KiB
54L2 cache: 512 KiB
55L3 cache: 18 MiB
56NUMA node0 CPU(s): 0,1
57Vulnerability Itlb multihit: KVM: Mitigation: VMX unsupported
58Vulnerability L1tf: Mitigation; PTE Inversion
59Vulnerability Mds: Mitigation; Clear CPU buffers; SMT Host state unknown
60Vulnerability Meltdown: Mitigation; PTI
61Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
62Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
63Vulnerability Spectre v2: Mitigation; Retpolines, IBPB conditional, IBRS_FW, STIBP disabled, RSB filling
64Vulnerability Srbds: Unknown: Dependent on hypervisor status
65Vulnerability Tsx async abort: Not affected
66Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid s
67 se4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflus
68 hopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
这样一来,基本可以确定,这个不同的行为就是 util-linux 升级版本产生的 break change.
在翻 RPM 的时候我发现 RHEL 9 的 util-linux 的上游源码使用的是 2.37.2 版本,即与 Ubuntu 22.04 使用的版本一致,因此以后的 RHEL 也许也将会看到类似的结果了。
评论