在 Unix/Linux 系统日常管理和系统维护的过程中,随时可能需要查看 CPU 的使用状态,并根据相应信息分析系统状况,判断系统的资源使用情况和系统负载情况。本文在介绍 Unix/Linux 系统中 CPU 相关机制和工具的基础上,对各工具进行了分析比较,并给出了自动化监控系统环境和 CPU 利用率的例子代码供读者参考。在 AIX 系统的 CPU 使用状态监控部分,我们将介绍 lparstat,mpstat 等工具。而在 Linux 系统 CPU 使用状态监控部分,我们将重点介绍 /proc 文件系统和 ps 等命令。
了解 AIX 系统中的可用 CPU 资源
AIX 系统中每个处理器在低位内存中有着对应的全局数据结构 PPDA (Per-processor Data Area),其中存储了处理器的各种配置信息和运行状态,比如时钟频率和 CPU 运行时间。AIX 系统接口查询 PPDA 中的数据并提供给终端用户或者应用程序使用。但在进行 CPU 监控之前,系统用户首先需要了解当前的系统环境和可用的计算资源。对于不同的系统环境,用户需要不同的监控策略。首先,对于没有划分微分区 (Micro Partition) 的服务器,系统用户可以通过很多操作系统接口得到机器实际可用的资源种类和数量。
硬件和操作系统没有使用虚拟化技术的系统
清单 1. 运行 prtconf 获得处理器的相关信息
prtconf | grep Processor
Processor Type: PowerPC_POWER6
Processor Implementation Mode: POWER 6
Processor Version: PV_6
Number Of Processors: 4
Processor Clock Speed: 4005 MHz
Model Implementation: Multiple Processor, PCI bus
+ proc0 Processor
+ proc2 Processor
+ proc4 Processor
+ proc6 Processor
Processor Type 表示了处理器的类型属于 Power 6 系列。这里同样可以知道本机的处理器个数为 4,并且时钟运行频率为 4G。运用类似的命令接口,比如 lsdev -Cc processor,也可以得到其他与 CPU 相关的配置信息。
使用微分区的系统
虚拟化作为一项成熟的技术,在 IBM eServer pSeries 服务器和 BladeCenter JS 刀片服务器中已经得到广泛的应用。所以我们有必要简单说明用户在常见的虚拟化环境,微分区 (Micro Partition) 中如何得到可用的资源状态。AIX 的命令接口在虚拟化环境下仍然可以使用,但是通常得到的结果是分配给当前虚拟机的虚拟处理器 (Virtual CPU) 的信息,而不是物理处理器 (Physical CPU) 的。
清单 2. 在微分区上运行 prtconf 获得虚拟处理器的信息
# prtconf | grep Processor
Processor Type: PowerPC_POWER5
Processor Implementation Mode: POWER 5
Processor Version: PV_5
Number Of Processors: 1
Processor Clock Speed: 1654 MHz
Model Implementation: Multiple Processor, PCI bus
+ proc0
以上输出表示本机当前被分配了一个虚拟处理器,及其硬���类型和运行频率。为了获得该虚拟机获得的物理处理器的数量,通常需要访问对应的 HMC (Hardware Management Console) 或者 AMM (Advanced Management Module) 来获得详细的信息和配置。下面的实例运行于 HMC。
清单 3. 在 HMC 上运行 lssyscfg 获得微分区的配置
hscroot@hmc:~> lssyscfg -r prof -m Server-9117-MMA-SN060DD72
--filter "lpar_ids=p6ml4n05"
name=p6ml4n05,lpar_name=p6ml4n05,lpar_id=6,lpar_env=aixlinux,
all_resources=0,min_mem=2048,desired_mem=3072,max_mem=4096,
min_num_huge_pages=0,desired_num_huge_pages=0,
max_num_huge_pages=0,mem_mode=ded,proc_mode=shared,min_proc_units=0.1,
desired_proc_units=0.2,max_proc_units=0.3,min_procs=1,desired_procs=1,
max_procs=1,sharing_mode=cap,uncap_weight=0,shared_proc_pool_id=0,
shared_proc_pool_name=DefaultPool,io_slots=none,lpar_io_pool_ids=none,
max_virtual_slots=10,
"virtual_serial_adapters=0/server/1/any//any/1,1/server/1/any//any/1",
virtual_scsi_adapters=2/client/1/vioserver/16/0,virtual_eth_adapters=none,
hca_adapters=none,boot_mode=norm,conn_monitoring=0,auto_start=0,
power_ctrl_lpar_ids=none,work_group_id=none,redundant_err_path_reporting=0,
bsr_arrays=0,lhea_logical_ports=23000000/2/1/5/none,
lhea_capabilities=23000000/0,
lpar_proc_compat_mode=default,electronic_err_reporting=null,
virtual_fc_adapters=none
此处跟 CPU 相关的重要字段有:
min_proc_units:为了启动该分区所需的最少的物理处理器个数
desired_proc_units: 该分区运行时通常需要的物理处理器个数
max_proc_units: 该分区在运行时允许获得的最多的物理处理器个数
使用负载分区的系统
从 AIX 6.1 开始,用户可以创建并使用负载分区 (Workload Partition,简称 WPAR)。负载分区可以模拟一个 AIX 6.1 用户环境,但在缺省情况下,CPU 资源不会被以 dedicated 方式划分给负载分区。所以 AIX 的系统命令,比如 lsdev 在负载分区下的输出结果会是当前系统没有处理器。负载分区中的用户,在系统响应不够及时的情况下,通常有如下几种可能:
负载分区本身被分配的资源不足
负载分区的其对应的宿主机的负载过大,或者出现了 IO 瓶颈
后面的段落会具体介绍如何确定和解决负载分区中跟 CPU 相关的系统瓶颈。
获得 AIX 系统中处理器资源的代码示例
本段的最后给出一段基于 Perl 的例子代码,在 AIX5.3 和 6.1 上测试通过,可以侦测当前的系统环境和 CPU 的类型和数量。这段代码首先运行系统命令 oslevel 得到当前系统的版本,如果是 AIX6.1 则运行命令 lparstat 判断当前系统是否为 WPAR。无论 AIX 系统的版本如何,都加参数 -i 运行命令 lparstat 来获得分区的个数,并以此判断是否使用了微分区技术。最后调用命令 prtconf 输出 CPU 的一些参数。
该段代码可以帮助用户快速了解当前环境,尤其适用于工作环境复杂或频繁变更的场景。需要指出的是对于使用了微分区技术的系统,代码的最后输出的是虚拟处理器的数量。需要了解系统中物理处理器和逻辑处理器状态的用户,可以参阅本文其他段落加以补充。
清单 4. 获得当前的系统环境和 CPU 的类型和数量的代码示例
# WPAR 仅存在于 AIX 6.1 系统
my oslevel = `oslevel`;
if (oslevel =~ m/6.1/)
{
# 在 WPAR 中不带参数运行 lparstat 命令只返回警告信息
my output = `lparstat`;
if (output =~ m/The output is applicable only to the Global Environment/)
{
print "This machine is one WPAR with following CPU assigned.n";
system ("prtconf | grep Processor");
exit 0;
}
}
# 使用– i 参数列出详细的配置信息
my @outputs = `lparstat -i`;
foreach my line (@outputs)
{
# 解析命令输出并得到分区个数
if (line !~ m/Partition Number/) {next;}
my (blank, partition_num) = split /Partition Numbers+:s/, line;
chomp partition_num;
if (partition_num eq '-') # full system 环境没有划分微分区
{
print "This machine is one full system without LPARs. The system has following
physical CPUs installed.n";
}elsif (partition_num > 1) # 如果存在多于一个的分区,该系统使用了微分区技术
{
print "This machine is one LPAR with virtual following CPUs installed.
To check the assignment of physical CPU, please log on HMC or AMM.n";
}else
{
print "Can not decide whether current environment is one LPAR or not.
Please check HMC or AMM to decide this.n";
}
}
# 打印处理器本身的参数
system ("prtconf | grep Processor");
exit 0;
使用 AIX 系统工具分析处理器的工作状态
在了解当前环境的可用 CPU 资源以后,可以对系统监控的对象和方法进行规划。多数情况下,操作系统提供的命令输出提供逻辑处理器 (Logical CPU) 的信息。在 IBM eServer pSeries 服务器和 BladeCenter JS 刀片��务器中,逻辑处理器通常通过并行多线程技术实现。下文是对该技术在 AIX 系统中应用的介绍。
并行多线程的查询和设置
并行多线程 (Simultaneous Multi-threading,简称 SMT) 是一种基于超标量 (superscalar) 体系结构处理器的技术,允许多个独立的线程在一个时钟周期内对多个功能处理单元 (Functional Unit) 发出指令。通常情况下,线程和功能处理单元的绑定是完全动态的。使用这项技术可以较明显的提高处理器的的实际利用率,进而表现出更强的运算性能。在 AIX 操作系统上,我们可以通过 smtctl 命令来查询和设置并行多线程的运行状态。
清单 5. 运行 smtctl 查询处理器对 SMT 技术的支持和当前的设置
smtctl
This system is SMT capable.
SMT is currently enabled.
SMT boot mode is not set.
SMT threads are bound to the same physical processor.
proc0 has 2 SMT threads.
Bind processor 0 is bound with proc0
Bind processor 1 is bound with proc0
proc2 has 2 SMT threads.
Bind processor 2 is bound with proc2
Bind processor 3 is bound with proc2
proc4 has 2 SMT threads.
Bind processor 4 is bound with proc4
Bind processor 5 is bound with proc4
proc6 has 2 SMT threads.
Bind processor 6 is bound with proc6
Bind processor 7 is bound with proc6
命令的结果说明了当前系统支持 SMT 技术,而且当前正在使用。后面的多行输出中详细说明了逻辑处理器和虚拟处理器之间的对应关系。系统中有四个可用的虚拟处理器 (Virtual CPU),因为开启了 SMT (Simultaneous MultiThreading) 功能,可以识别出八个逻辑上的虚拟处理器 (Logical CPU)。
在缺省情况下,系统中的 SMT 应被使用以增强性能。当用户需要调整���统的 SMT 设置时,同样可以使用 smtctl 命令。具体参数请查阅命令说明。在负载分区情况下,SMT 设置不允许被直接修改。用户需要对负载分区的宿主机修改 SMT 配置,这会对该系统中的所有负载分区生效。而在微分区环境下,用户可以自主调整并行多线程的配置。
系统处理器负载的查询和分析
在了解系统中并行多线程的设置以后,用户需要得到不同时间段内处理器的使用状态。为此 AIX 系统提供了丰富的系统接口。用户可以根据不同的情况选用他们,检查和判断系统中 CPU 的运行状态。本文仅以 lparstat 和 mpstat 为例进行说明。
lparstat 命令
上文的例子代码使用了 lparstat。这个命令可以在各种系统环境,如负载分区中使用,得到当前系统的配置和部分运行状态,其中的部分内容与 CPU 直接相关。在 AIX 6.1 操作系统中,lparstat 也可以用来显示负载分区 (Workload Partition) 的信息,比如负载分区使用的 CPU 资源。用户可以查阅手册得到该命令的详细说明。
lparstat 命令非常适合获得当前系统或分区的配置信息,但是用来监控 CPU 负载有两个主要的不足。首先这条命令不能得到单个处理器的负载情况,所以不能用来直接确定多处理器负载不均的问题;其次这条命令在 AIX 6.1 系统上的支持的参数与 5.3 相比变化较大。所以本文主要介绍 mpstat 命令,用于检测 AIX 系统中的 CPU 状态。
mpstat 命令
与 lparstat 命令相似,mpstat 可以自动识别当前的系统设置,比如是否开启了 SMT 功能。与 lparstat 不同的是,mpstat 可以得到详细的单个处理器的运行状况。
图 1. 在没有微分区 (Micro Partition) 的系统上运行 mpstat 获得处理器负载
该命令检测系统中全部处理器的利用情况,并且给出各项的总和。下面是几个常用的输出项
lcpu: 工作的逻辑处理器的个数
us: 运行的用户程序所占用的 CPU 百分比
sy: 运行的内核程序所占用的 CPU 百分比
wa: CPU 用来等待 IO 所占用的百分比
id: CPU 空闲且不等待 IO 所占用的百分比
通常情况下,CPU0 的负载会略高于其他处理器。在其他处理器负载相差不多而且 CPU0 的负载不太高的情况下,可以认为是正常的情况。反之则可能存在系统或应用程序上的分配问题。
在显示的内容中,如果 wa 的值过高,则表示应用程序有过多的时间等待 IO 操作,外存的访问存在性能瓶颈。如果 id 的值如果持续低于 30,而且 wa 不高,则表明 CPU 比较繁忙 , 可以考虑对应用程序进行优化。如果是微分区或负载分区系统中,应当考虑是否需要分配更多的处理器资源。
mpstat 命令提供了参数,可以周期性的检测并汇报系统状态。在 mpstat 命令的输出满足用户需要的情况下,用户可以指定合适的间隔并以后台运行 mpstat,以实现对系统 CPU 的持续监控。下面的命令会在一天的时间内每隔半小时自动搜集一次系统信息。
mpstat 1800 48 > /tmp/mpstat_output &
用户可以有策略的检查输出文件中的内容,以确定系统的运行状态。
捕捉处理器异常状态的代码示例
下面一段 Perl 代码测试于 AIX5.3 和 6.1 系统,首先运行系统命令 smtctl 检查并行多线程技术的开启状态,然后依次检查 mpstat 命令输出文件中的每行内容,并把可能表示异常情况的行存入一个数组。
清单 6. 捕捉处理器异常状态的代码示例
my output = `smtctl`;
# 如果 SMT 技术没有被激活,通常我们需要激活它
if (output =~ m/This system is SMT capable.*SMT is currently disabled/)
{
warn "This system can have SMT enabled, but has not. This means potential performance
issue in some applications. Command smtctl can be used to enable SMT. Notice that
change can NOT be directly done on workload partition.n";
}
# 解析文本文件 /tmp/mpstat_output。用户应该先运行 mpstat 并把输出重定向来得到这个文件。
my file = '/tmp/mpstat_output';
open (FILE, "<file") or die "No mpstat output file available.
Please run mpstat first.n";
my @output = <FILE>;
close FILE;
my @notice;
foreach my line (@output)
{
chomp line;
# 跳过空行和提示行
if (line !~ /S+/) {next;}
if (line =~ m/System configuration/ || line =~/cpus+min/) {next;}
# 删除每行起始的空格
line =~ s/^s+//g;
my (cpu, min, maj, mpc, int, cs, ics, rq, mig, lpa, sysc, us, sy,
wt, id, pc);
= split /s+/, line;
# 通常系统中不应有过长的运行队列,过多的线程迁移,过长的等待时间或过少的空闲时间
if (rq > 5 || mig > 5 || wt > 5 || id < 10)
{
push @notice, line;
}
}
用户可以根据自己系统的版本对例子代码进行修改,并且选择如何处理这些异常。比较常见的处理有把异常内容在标准输出设备上输出,或者发邮件给系统的管理员。为了能够自动的实现这一功能,用户也可以把修改过的脚本定义成系统的 crontab 任务,实现在一定时间段内的定时监控。���发现了异常状态以后,通常需要确定异常状态是否与特定的进程或程序相关,再进一步对操作系统或特定进程进行判断。