Solaris 10 资源管理器开发者指南

第 6 章 动态资源池

本章介绍资源池及其属性。

资源池概述

资源池提供了用于管理处理器集和线程调度类的框架。资源池用于对计算机资源进行分区。通过资源池可以分散工作负荷,使各工作负荷对特定资源的占用不会发生冲突。在具有混合工作负荷的系统上,这种资源预留有助于获得可预测的性能。

有关资源池以及用于管理资源池的示例命令的概述,请参见《系统管理指南:Solaris Containers-资源管理和 Solaris Zones》中的第 12  章 “动态资源池(概述)”《系统管理指南:Solaris Containers-资源管理和 Solaris Zones》中的第 13  章 “管理动态资源池(任务)”

处理器集将系统中的 CPU 分组到一个有界限的实体中,在该实体中进程可以采用独占方式运行。其中的进程不能扩展到该处理器集外,而其他进程也不能扩展到该处理器集内。处理器集可以将具有类似特征的任务组合在一起,并设置针对 CPU 使用的硬限制(上限)。

资源池框架用于定义具有最大和最小 CPU 计数要求的软处理器集。此外,该框架还为该处理器集提供了一个硬定义调度类。

资源池定义以下内容

调度类

调度类为基于算术逻辑的线程提供不同的 CPU 访问特性。调度类包括:

有关公平共享调度程序以及用于管理公平共享调度程序的示例命令的概述,请参见《系统管理指南:Solaris Containers-资源管理和 Solaris Zones》中的第 8  章 “公平共享调度程序(概述)”《系统管理指南:Solaris Containers-资源管理和 Solaris Zones》中的第 9  章 “管理公平共享调度程序(任务)”

请不要在 CPU 集中混合调度类。如果在 CPU 集中混合调度类,则系统性能可能会不稳定或不可预测。请使用处理器集按照应用程序特征分别部署应用程序。请指定使应用程序能够达到最佳性能的调度类。有关各个调度类的特征的更多信息,请参见 priocntl(1)。

有关资源池的概述以及对何时使用资源池的讨论,请参见第 6 章,动态资源池

动态资源池约束和目标

libpool 库定义了可用于各种实体(使用池功能管理)的属性。每个属性都属于以下类别:

配置约束

约束定义了属性的限制。典型的约束是在 libpool 配置中指定的最大和最小分配量。

目标

目标可以更改当前配置的资源分配,以生成遵循已建立约束的新的候选配置。(请参见 poold(1M)。)目标包含以下类别:

与工作负荷有关

与工作负荷有关的目标将依据工作负荷强加的条件有所变化。与工作负荷有关的目标示例为 utilization 目标。

与工作负荷无关

与工作负荷无关的目标不会依据工作负荷强加的条件发生变化。与工作负荷无关的目标示例为 cpu locality 目标。

目标可以采用可选的前缀来指示目标的重要性。为确定目标的重要性,将在目标中增加此前缀(是 0 到 INT64_MAX 之间的整数)。

系统属性

system.bind-default可写布尔值

如果在 /etc/project 中找不到指定的池,请绑定到 pool.default 属性设置为 TRUE 的池。

system.comment可写字符串

系统的用户说明。缺省的池命令不使用 system.comment,但通过 poolcfg 实用程序启动配置时除外。此时,系统会将提示性消息置于该配置的 system.comment 属性中。

system.name可写字符串

配置的用户名称。

system.version(只读整数)

处理此配置所需的 libpool 版本。

池属性

所有的池属性都是可写的。

pool.active可写布尔值

如果为 TRUE,则表示该池处于活动状态。

pool.comment可写字符串

池的用户说明。

pool.default可写布尔值

如果为 TRUE,则表示该池为缺省池。请参见 system.bind-default 属性。

pool.importance可写整数

该池的相对重要性。用于可能的资源争用解决方案。

pool.name可写字符串

池的用户名称。setproject(3PROJECT) 使用 pool.name 作为 project(4) 数据库中的 project.pool 项目属性的值。

pool.scheduler可写字符串

与该池的使用者绑定的调度程序类。此属性是可选的,如果未指定,则调度程序对该池使用者的绑定将不受影响。有关各个调度类的特征的更多信息,请参见 priocntl(1)。调度程序类包括:

  • RT(代表实时调度程序)

  • TS(代表分时调度程序)

  • IA(代表交互式调度程序)

  • FSS(代表公平共享调度程序)

  • FX(代表固定优先级调度程序)

处理器集属性

pset.comment可写字符串

资源的用户说明。

pset.default(只读布尔值)

标识缺省的处理器集。

pset.escapable可写布尔值

表示是否为此 pset 设置 PSET_NOESCAPE。请参见 pset_setattr(2) 手册页。

pset.load(只读无符号整数)

此处理器集的负载。最低值为 0。该值将随着处理器集上的负载(由系统运行队列中的作业数度量)以线性方式增加。

pset.max可写无符号整数

此处理器集中允许的最大 CPU 数。

pset.min可写无符号整数

此处理器集中允许的最小 CPU 数。

pset.name可写字符串

资源的用户名称。

pset.size(只读无符号整数)

此处理器集的当前 CPU 数。

pset.sys_id(只读整数)

系统指定的处理器集 ID。

pset.type(只读字符串)

命名资源类型。所有处理器集的值都为 pset

pset.units(只读字符串)

标识与大小相关的属性的意义。所有处理器集的值都为 population

cpu.comment可写字符串

CPU 的用户说明。

使用 libpool 处理池配置

libpool(3LIB) 池配置库定义了用于读取和写入池配置文件的接口。该库还定义了用于提交现有配置以成为运行的操作系统配置的接口。<pool.h> 头文件提供了所有库服务的类型和函数声明。

在资源池功能中,引入了“池”这个一般性的概念,用来指可绑定到进程的资源的集合。可以采用持久方式配置、分组并标记处理器集和其他实体。可以将工作负荷组件与系统总资源的一部分相关联。libpool(3LIB) 库提供了用于访问资源池功能的 C 语言 API。pooladm(1M)、poolbind(1M) 和 poolcfg(1M) 可通过从 shell 中调用命令来使用资源池功能。

处理 pset

以下列表包含与创建或销毁 pset 以及处理 pset 关联的函数。

processor_bind(2)

将 LWP(lightweight process,轻量进程)或一组 LWP 绑定到指定的处理器。

pset_assign(2)

为处理器集分配处理器。

pset_bind(2)

将一个或多个 LWP(lightweight processes,轻量进程)绑定到处理器集。

pset_create(2)

创建不包含处理器的空处理器集。

pset_destroy(2)

销毁处理器集并释放关联的成员处理器和进程。

pset_setattr(2), pset_getattr(2)

设置或获取处理器集属性。

资源池 API 函数

本节列出了所有的资源池函数。每个函数都带有指向相应手册页的链接和有关该函数用途的简短说明。根据函数执行操作还是查询,函数分为两组:

用于交换集的 libpool 的导入接口与本文档中定义的接口相同。

用于对资源池和关联元素执行操作的函数

本节中列出的接口用于执行与池和关联元素相关的操作。

pool_associate(3POOL)

将资源与指定的池关联起来。

pool_component_to_elem(3POOL)

将指定的组件转换为池元素类型。

pool_conf_alloc(3POOL)

创建池配置。

pool_conf_close(3POOL)

关闭指定的池配置并释放关联资源。

pool_conf_commit(3POOL)

提交对指定池配置所做的更改以进行永久存储。

pool_conf_export(3POOL)

将给定的配置保存到指定位置。

pool_conf_free(3POOL)

释放池配置。

pool_conf_open(3POOL)

在指定的位置创建池配置。

pool_conf_remove(3POOL)

删除对配置的永久存储。

pool_conf_rollback(3POOL)

将配置状态恢复到池配置的永久存储中保留的状态。

pool_conf_to_elem(3POOL)

将指定的池配置转换为池元素类型。

pool_conf_update(3POOL)

更新内核状态的库快照。

pool_create(3POOL)

使用缺省属性和每种类型的缺省资源创建新的池。

pool_destroy(3POOL)

破坏指定的池。关联的资源不会被修改。

pool_dissociate(3POOL)

删除给定资源与池之间的关联。

pool_put_property(3POOL)

将有关元素的命名属性设置为指定的值。

pool_resource_create(3POOL)

使用所提供配置的指定名称和类型创建新的资源。

pool_resource_destroy(3POOL)

从配置文件中删除指定的资源。

pool_resource_to_elem(3POOL)

将指定的池资源转换为池元素类型。

pool_resource_transfer(3POOL)

将基本单位从源资源传输到目标资源。

pool_resource_xtransfer(3POOL)

将指定组件从源资源传输到目标资源。

pool_rm_property(3POOL)

从元素中删除命名的属性。

pool_set_binding(3POOL)

将指定的进程绑定到与正在运行的系统中的池关联的资源。

pool_set_status(3POOL)

修改池功能的当前状态。

pool_to_elem(3POOL)

将指定的池转换为池元素类型。

pool_value_alloc(3POOL)

分配并返回池属性值的不透明容器。

pool_value_free(3POOL)

释放分配的属性值。

pool_value_set_bool(3POOL)

设置 boolean 类型的属性值。

pool_value_set_double(3POOL)

设置 double 类型的属性值。

pool_value_set_int64(3POOL)

设置 int64 类型的属性值。

pool_value_set_name(3POOL)

为池属性设置 name=value 对。

pool_value_set_string(3POOL)

复制已传递的字符串。

pool_value_set_uint64(3POOL)

设置 uint64 类型的属性值。

用于查询资源池和关联元素的函数

本节中列出的接口用于执行与池和关联元素相关的查询。

pool_component_info(3POOL)

返回描述给定组件的字符串。

pool_conf_info(3POOL)

返回描述整个配置的字符串。

pool_conf_location(3POOL)

返回为指定配置的 pool_conf_open() 提供的位置字符串。

pool_conf_status(3POOL)

返回池配置的有效性状态。

pool_conf_validate(3POOL)

检查给定配置内容的有效性。

pool_dynamic_location(3POOL)

返回池框架用于存储动态配置的位置。

pool_error(3POOL)

返回通过调用资源池配置库函数记录的最终故障的错误值。

pool_get_binding(3POOL)

返回正在运行的系统中的池名称,该池包含与指定进程绑定的资源集。

pool_get_owning_resource(3POOL)

返回当前包含指定组件的资源。

pool_get_pool(3POOL)

返回具有所提供配置中的指定名称的池。

pool_get_property(3POOL)

检索元素中的已命名属性的值。

pool_get_resource(3POOL)

返回具有所提供配置中的给定名称和类型的资源。

pool_get_resource_binding(3POOL)

返回正在运行的系统中的池名称,该池包含与给定进程绑定的资源集。

pool_get_status(3POOL)

检索池功能的当前状态。

pool_info(3POOL)

返回指定池的说明。

pool_query_components(3POOL)

检索与指定的属性列表匹配的所有资源组件。

pool_query_pool_resources(3POOL)

返回当前与池关联的以 NULL 结尾的资源数组。

pool_query_pools(3POOL)

返回与指定的属性列表匹配的池列表。

pool_query_resource_components(3POOL)

返回构成指定资源的以 NULL 结尾的组件数组。

pool_query_resources(3POOL)

返回与指定的属性列表匹配的资源列表。

pool_resource_info(3POOL)

返回指定资源的说明。

pool_resource_type_list(3POOL)

枚举此平台上的池框架支持的资源类型。

pool_static_location(3POOL)

返回池框架用于存储缺省池框架实例化配置的位置。

pool_strerror(3POOL)

返回每个有效池错误代码的说明。

pool_value_get_bool(3POOL)

获取 boolean 类型的属性值。

pool_value_get_double(3POOL)

获取 double 类型的属性值。

pool_value_get_int64(3POOL)

获取 int64 类型的属性值。

pool_value_get_name(3POOL)

返回为指定池属性指定的名称。

pool_value_get_string(3POOL)

获取 string 类型的属性值。

pool_value_get_type(3POOL)

返回指定的池值包含的数据类型。

pool_value_get_uint64(3POOL)

获取 uint64 类型的属性值。

pool_version(3POOL)

获取池库的版本号。

pool_walk_components(3POOL)

调用对资源中包含的所有组件的回调。

pool_walk_pools(3POOL)

调用在配置中定义的所有池的回调。

pool_walk_properties(3POOL)

调用对为给定元素定义的所有属性的回调。

pool_walk_resources(3POOL)

调用对与池关联的所有资源的回调。

资源池代码示例

本节包含资源池接口的代码示例。

确定资源池中的 CPU 数

sysconf(3C) 提供有关整个系统中的 CPU 数的信息。以下示例提供了用于确定特定应用程序的池 pset 中所定义 CPU 数的粒度。

本示例的要点包括以下内容:

pool_value_t *pvals[2] = {NULL};  /* pvals[] should be NULL terminated */



/* NOTE: Return value checking/error processing omitted */

/* in all examples for brevity */



conf_loc = pool_dynamic_location();

conf = pool_conf_alloc();

pool_conf_open(conf, conf_loc, PO_RDONLY);

my_pool_name = pool_get_binding(getpid());

my_pool = pool_get_pool(conf, my_pool_name);

pvals[0] = pool_value_alloc();

pvals2[2] = { NULL, NULL };

pool_value_set_name(pvals[0], "type");

pool_value_set_string(pvals[0], "pset");



reslist = pool_query_pool_resources(conf, my_pool, &nelem, pvals);

pool_value_free(pvals[0]);

pool_query_resource_components(conf, reslist[0], &nelem, NULL);

printf("pool %s: %u cpu", my_pool_ name, nelem);

pool_conf_close(conf);

列出所有的资源池

以下示例列出了在应用程序的池 pset 中定义的所有资源池。

该示例的要点包括以下内容:

conf	= pool_conf_alloc();

pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY);

pl = pool_query_pools(conf, &nelem, NULL);

pval = pool_value_alloc();

for (i = 0; i < nelem; i++) {

    pool_get_property(conf, pool_to_elem(conf, pl[i]), "pool.name", pval);

    pool_value_get_string(pval, &fname);

    printf("%s\n", name);

}

pool_value_free(pval);

free(pl);

pool_conf_close(conf);

报告给定池的池统计信息

以下示例报告了指定池的统计信息。

该示例的要点包括以下内容:

printf("pool %s\n:" pool_name);

pool = pool_get_pool(conf, pool_name);

rl = pool_query_pool_resources(conf, pool, &nelem, NULL);

for (i = 0; i < nelem; i++) {

  pool_get_property(conf, pool_resource_to_elem(conf, rl[i]), "type", pval);

  pool_value_get_string(pval, &type);

  type = strdup(type);

  snprintf(prop_name, 32, "%s.%s", type, "name");

  pool_get_property(conf, pool_resource_to_elem(conf, rl[i]), 

        prop_name, pval);

  pool_value_get_string(val, &res_name);

  res_name = strdup(res_name);

  snprintf(prop_name, 32, "%s.%s", type, "load");

  pool_get_property(conf, pool_resource_to_elem(conf, rl[i]), 

        prop_name, pval);

  pool_value_get_uint64(val, &load);

  snprintf(prop_name, 32, "%s.%s", type, "size");

  pool_get_property(conf, pool_resource_to_elem(conf, rl[i]), 

        prop_name, pval);

  pool_value_get_uint64(val, &size);

  printf("resource %s: size %llu load %llu\n", res_name, size, load);

  free(type);

  free(res_name);

}

free(rl);

设置 pool.comment 属性并添加新属性

以下示例设置了 psetpool.comment 属性。该示例还在 pool.newprop 中创建了新的属性。

该示例的要点包括以下内容:

pool_set_comment(const char *pool_name, const char *comment)

{

  pool_t *pool;

  pool_elem_t *pool_elem;

  pool_value_t *pval = pool_value_alloc(); 

  pool_conf_t  *conf = pool_conf_alloc();

  /* NOTE: need to be root to use PO_RDWR on static configuration file */

  pool_conf_open(conf, pool_static_location(), PO_RDWR);

  pool = pool_get_pool(conf,  pool_name);

  pool_value_set_string(pval, comment);

  pool_elem = pool_to_elem(conf, pool);

  pool_put_property(conf, pool_elem, "pool.comment", pval);

  printf("pool %s: pool.comment set to %s\n:" pool_name, comment);

  /* Now, create a new property, customized to installation site */

  pool_value_set_string(pval, "New String Property");

  pool_put_property(conf, pool_elem, "pool.newprop", pval);

  pool_conf_commit(conf, 0); /* NOTE: use 0 to ensure only */

                             /* static file gets updated */

  pool_value_free(pval);

  pool_conf_close(conf);

  pool_conf_free(conf);

  /* NOTE: Use "pooladm -c" later, or pool_conf_commit(conf, 1) */

  /* above for changes to the running system */

}

另一种修改池的注释并添加新的池属性的方法是使用 poolcfg(1M)。

poolcfg -c 'modify pool pool-name (string pool.comment = "cmt-string")'

poolcfg -c 'modify pool pool-name (string pool.newprop = 

                                   "New String Property")'

与资源池关联的编程问题

编写应用程序时,请考虑以下问题。