Unix/Linux 系统自动化管理 CPU 管理篇(3)
- UID
- 1066743
|
Unix/Linux 系统自动化管理 CPU 管理篇(3)
了解 Linux 系统中的可用 CPU 资源Linux 系统由于其开放性的优势,近年来在易用性,稳定性和市场占有率上获得了一定的进步。Linux 提供了一个特殊而强大的伪文件系统 proc。在设计之初,proc 的目的是用户能够方便快捷的访问进程。经过长时间的发展,proc 文件系统已经可以提供查询系统状态,例如 CPU 状态,更改系统参数等多方面的功能。
在绝大多数的 Linux 发行版中,/proc 文件系统在系统启动时缺省挂载到目录 /proc,作为操作系统和应用进程的接口。用户和应用程序可以通过 proc 得到系统的信息,并可以改变内核的某些参数。/proc 目录中包含了许多特殊文件以允许对驱动和内核信息进行高层访问。只要用户或应用程序有正确的访问权限,它们就可以通过读写这些文件来获得信息或设置参数。由于 Linux 系统的状态,如进程占用的资源,是动态改变的,所以用户或应用程序读取 proc 文件时,proc 文件系统是动态从系统内核读出所需信息并提交的。当系统重启或者电源关闭的时候,/proc 系统中原有的数据和信息将全部丢失。但在下次系统启动时会重新建立。下面会介绍与 CPU 直接相关的两个 /proc 文件,cpuinfo 和 loadavg。
文件 /proc/cpuinfo 存放了 Linux 系统的 CPU 信息。随着 Linux 发行版,CPU 的类型、设置的不同,该文件的内容会有比较大的差异。有些发行版本的 cpuinfo 文件包含了诸如 CPU 步进 (stepping),制造厂商等详细的 CPU 硬件信息。而在一部分发行版中,该文件仅包含了每个处理器的基本信息,比如时钟频率。需要用户注意的是,在使用了 SMT 技术的系统上,/proc/cpuinfo 显示的是逻辑处理器的个数和属性。
清单 7. 在 IBM JS BladeCenter 上读取 /proc/cpuinfo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| # cat /proc/cpuinfo
processor : 0
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 1
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 2
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 3
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 4
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 5
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 6
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
processor : 7
CPU : POWER6 (raw), altivec supported
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
clock : 4005.000000MHz
revision : 3.1 (pvr 003e 0301)
timebase : 512000000
platform : pSeries
model : IBM,7998-61X
machine : CHRP IBM,7998-61X
|
Linux 支持众多的硬件类型,并且有很多有差异的发行版。没有统一的命令可以得到或查询 SMT 的状态。但在基于 Power 核心的 IBM 服务器上,可以使用 ppc_64 命令。
清单 8. 使用 ppc_64 命令获得 SMT 的设置1
2
| # ppc64_cpu --smt
smt is on
|
这条命令同样可以用来改变 SMT 的设置,详细用法请参阅命令说明。
在了解到 SMT 被开启以后分析 /proc/cpuinfo 文件的内容。可以看到系统中共有八个逻辑处理器 (Logical CPU),所以物理处理器的个数是 8 / 2 = 4。它们都是 IBM pSeries 系列的 Power 6 处理器,支持 Altivec 指令集,运行于 4GHz,修订版本为 3.1,基准时钟频率 (time base) 为 512MHz。在文件最后的内容表示了机器的硬件类型 7998-61X。查询 IBM 网站可知这是 IBM BladeCenter JS22 的刀片服务器。
因为 IBM 的微分区技术构建于 Linux 系统之下,所以为了获得微分区的被分配的物理处理器个数,需要访问 HMC(Hardware Management Console) 或 AMM(Advanced Management Module)。具体使用可参阅本文的 AIX 部分或者 IBM 的使用说明。
从 2.6.20 开始,Linux 内核引入了 KVM (Kernel-based Virtual Machine) 作为标准的虚拟化解决方案。在 KVM 中 /proc/cpuinfo 的内容会与宿主机不同,一些情况下可以帮助用户知道当前的系统是否是 KVM 下的虚拟环境
清单 9. 在 KVM 的虚拟机中读取 /proc/cpuinfo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
CPU family : 6
model : 2
model name : QEMU Virtual CPU version 0.9.1
stepping : 3
CPU MHz : 2660.129
cache size : 2048 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
CPUid level : 2
wp : yes
flags : fpu de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36
clflush mmx fxsr sse sse2 nx lm up pni
bogomips : 5326.47
|
在模式名 (model name) 中可以知道,本机使用了基于 QEMU 模拟器的虚拟处理器。
IBM 的 System x 系列服务器使用了不同的硬件类型,用户可以仅通过读取 /proc/cpuinfo 的内容获得包括 SMT 等的系统设置。
获得系统处理器配置的代码示例下面的例子代码适用于使用 Power CPU 或者 Intel CPU 的 Linux 系统,并在 Redhat 企业服务器版和 Suse 企业服务器版上测试通过。它首先运行命令 arch 判断当前系统的运行平台,并读取 /proc/cpuinfo 文件。在 Power 平台上调用特有的 ppc64_cpu 命令获得 SMT 配置,并读取 /proc/ppc64/lparcfg 文件以获得 CPU 的运行模式;在 System x 系列服务器上则是通过解析文件 /proc/cpuinfo 的内容来获得 SMT 配置。代码的最后依次输出了系统中 CPU 资源的数量、配置、运行模式和类型。
清单 10. 获取系统 CPU 资源配置的代码示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| # 得到 /proc/cpuinfo 文件的内容
my $cpu_file = '/proc/cpuinfo';
open FILE, "<$cpu_file" or die "Failed to open $cpu_file.\n";
my @contents = <FILE>;
close FILE;
my ($smt, $dedicate);
# Power 服务器上运行的 Linux 发行版有自己的命令和配置文件
my $arch = `arch`;
if ($arch =~ /ppc64/){
# 得到 Power 服务器上的 SMT 配置
my $output = `ppc64_cpu --smt`;
if ($output =~ m/off/){
$smt = "off";
}elsif ($output =~ m/on/){
$smt = "on";
}else{
die "Command ppc64_cpu does not work well. Please reinstall powerpc-utils
to fix this issue.\n";
}
# 从 lparcfg 文件读出处理器运行模式
my $cfg_file = '/proc/ppc64/lparcfg';
open FILE, "<$cfg_file" or die "Failed to open $cfg_file.\n";
my @cfgs = <FILE>;
close FILE;
foreach my $line (@cfgs){
if ($line =~ /shared_processor_mode=0/){
$dedicate = 1; # dedicated CPU
last;
}
}
}
# 解析 /proc/cpuinfo 文件的内容
my $proc_num = 0;
my $line_num = 0;
my (@physical_ids, $latest_proc_line_num);
foreach my $line (@contents){
$line_num ++;
chomp $line;
# 得到虚拟处理器的个数
if ($line =~ /processor\s+: \d/){
$proc_num ++;
$latest_proc_line_num = $line_num;
}
if ($arch =~ /86/ && $line =~ /physical id/ && !grep (/^\Q$line\E$/, @physical_ids)){
push @physical_ids, $line;
}
}
# 得到 x86 构架系统的 SMT 配置
my $phy_proc_num = scalar(@physical_ids);
if ($arch =~ /86/ && ($proc_num > $phy_proc_num)){
$smt = "on";
}elsif ($arch =~ /86/ && ($proc_num == $phy_proc_num)){
$smt = "off";
}
# 得到 Power 服务器的虚拟处理器个数
my $vir_proc_num;
if ($arch =~ /ppc64/ && $smt eq "on"){
$vir_proc_num = $proc_num/2;
}elsif ($arch =~ /ppc64/ && $smt eq "off"){
$vir_proc_num = $proc_num;
}
# 输出处理器个数
if ($arch =~ /86/){
print "There exist $phy_proc_num physical processors and $proc_num logical
processors in the system.\n";
}elsif ($arch =~ /ppc64/){
print "There exist $vir_proc_num virtual processors and $proc_num logical
processors in the system.\n";
}
# 输出 SMT 配置
if ($smt eq "on"){
print "SMT is $smt on this machine.\n";
}else{
print "SMT is $smt on this machine. This means potential performance issue in some
applications. Please make sure that's the configuration you want.\n";
}
# 输出处理器运行模式
if ($arch =~ /ppc64/ && $dedicate){
print "System processors are dedicated.\n";
}elsif ($arch =~ /ppc64/ && !$dedicate){
print "System processors are shared.\n";
}
# 输出 /proc/cpuinfo 中的处理器关键信息
for (my $i = $latest_proc_line_num; $i < scalar(@contents); $i ++){
print "$contents[$i]\n";
}
|
|
|
|
|
|
|