使用 动态处理器释放

从机器类型 7044 的 270 型开始,所有带有超过两个处理器的系统的硬件都能够检测到由固件收集的可更正错误。 这些错误都不是致命的错误,并且只要保持它们极少发生,忽略这些错误也是安全的。 但是,当特定处理器上看起来出现了故障模式时,此模式可能指出此组件很可能在不久的将来会出现无法恢复的故障。 固件基于故障率和阈值分析做出此预测。

AIX®实现了持续的硬件监控,并定期轮询固件以查找硬件错误。 当处理器错误数达到阈值,并且固件识别出此系统组件将失败的不同概率时,固件会向 AIX 返回错误报告,并将该错误记录在系统错误日志中。 此外,在多处理器系统上,根据故障类型, AIX 会尝试停止使用不可信的处理器并将其释放。 此故障称为动态处理器释放

此时,固件为了随后的重新启动将处理器标记为持久释放,直到维护人员替换处理器。

对应用程序的潜在影响

处理器重分配对于绝大多数应用程序而言不明显,包括驱动程序和内核扩展。 但是,您可以使用 AIX 发布的接口来确定应用程序或内核扩展是否正在多处理器机器上运行,找出有多少个处理器,并将线程绑定到特定处理器。

将进程或线程绑定到处理器的 bindprocessor 接口使用绑定 CPU 号。 绑定 CPU 号在范围 [0.. N-1] 中,其中 N 是 CPU 的总数。 为避免中断在 CPU 编号中没有 "孔" 的应用程序或内核扩展, AIX 始终使应用程序显示为如同 CPU 是要释放的 "最后一个" (最高编号) 绑定 CPU。 例如,在 8 通道 SMP 上,绑定 CPU 号为[0..7]。 如果已释放一个处理器,那么可用的 CPU 总数为 7,并且它们的编号为[0..6]。 在外部,不管哪个物理处理器发生故障,CPU 7 看起来都已消失。

注: 在此描述的其余部分中,术语 CPU 用于逻辑实体,术语 处理器 用于物理实体。

如果 AIX 在需要释放其中一个处理器时以静默方式终止其绑定线程或强制将其移动到另一个 CPU ,那么使用进程/线程绑定的应用程序或内核扩展可能会中断。 动态处理器释放提供了编程接口,因此可以通知那些应用程序和内核扩展即将发生处理器重分配。 当这些应用程序和内核扩展获取了该信息时,它们负责将它们的绑定线程和关联资源(例如:计时器请求块)从最后绑定 CPU 标识移走,并使它们自己适应新的 CPU 配置。

如果,在应用程序和内核扩展的通知之后,一些线程还被绑定到最后绑定 CPU 标识,那么将放弃释放。 在这种情况下, AIX 会在错误日志中记录释放已异常中止的事实,并继续使用有问题的处理器。 当处理器最终发生故障时,它会引起整个系统故障。 那么,将线程绑定到 CPU 的应用程序和内核扩展获取即将发生处理器重分配的通知,并对此通知采取行动就十分重要。

即使在释放无法进行的极少数情况下,动态处理器释放仍然会对系统管理员提前发出警告。 通过在错误日志中记录错误,将提供在系统上调度维护操作的机会,以在发生全局系统故障之前替换有故障的组件。

处理器释放事件的流程

处理器释放的典型事件流如下:

  1. 固件检测到一个处理器已达到可恢复错误阈值。
  2. AIX 将固件错误报告记录在系统错误日志中,并在支持处理器释放的机器上执行时启动释放过程。
  3. AIX 通知绑定到最后一个绑定 CPU 的非内核进程和线程。
  4. AIX 等待所有绑定线程离开最后一个绑定 CPU。 如果线程保持绑定,那么 AIX 最终会超时 (10 分钟后) 并异常中止释放。 否则, AIX 将调用先前注册的高可用性事件处理程序 (HAEH)。 HAEH 可能返回将放弃释放的错误。 否则, AIX 将继续执行释放过程,并最终停止发生故障的处理器。

如果在释放的任何时间点发生故障,那么 AIX 会记录该故障,并指示释放异常中止的原因。 系统管理员可以查看该错误日志,采取纠正措施(如果可能)并重新启动释放。 例如,如果因为至少有一个应用程序无法解除绑定其已绑定的线程,释放异常终止,那么系统管理员可以停止应用程序、重新启动释放(这次应该继续)并重新启动应用程序。

用来处理单个处理器的编程接口

以下部分描述了可用的编程接口:

用来确定系统上 CPU 数目的接口

sysconf 子例程

sysconf 子例程使用下面的参数返回处理器数:
  • _SC_NPROCESSORS_CONF:已配置处理器数
  • _SC_NPROCESSORS_ONLN:联机处理器数

sysconf 子例程返回的值_SC_NPROCESSORS_CONF将在重新引导之间保持恒定。 单处理器 (UP) 机器由 1 标识。 大于 1 的值指示多处理器 (MP) 机器。 _SC_NPROCESSORS_ONLN 参数的返回值是活动 CPU 计数,在处理器每次被取消分配时会减少。

_system_configuration.ncpus 字段标识机器上的活动 CPU 数。 g 此字段类似于 _SC_NPROCESSOR_ONLN 参数。

对于必须识别最初在引导时可用的处理器数的代码,会将 ncpus_cfg 字段添加到_system_configuration表,在重新引导之间保持常量。

CPU 由范围在 [0..(ncpus-1)] 之间的绑定 CPU 标识来标识。 处理器还有物理 CPU 号,此 CPU 号取决于它们在哪块 CPU 板上,顺序如何等等。 处理 CPU 号的命令和子例程通常使用绑定 CPU 号。 要简化对不同的 CPU 号的转换,绑定 CPU 号是在 [0..(ncpus-1)] 范围内的相邻数字。 结果是,从用户的角度,进行处理器重分配时,不管哪一个物理处理器产生故障看起来都是编号最大(“最后”)的绑定 CPU 消失了。

注: 为了避免出现问题,请使用 ncpus_cfg 变量来确定特定系统的最大可能绑定 CPU 数。

用来将线程绑定至特定处理器的接口

bindprocessor 命令bindprocessor 编程接口允许您将线程或进程绑定到由其绑定 CPU 号指定的特定 CPU。 两个接口都仅允许您将线程或者进程绑定到活动 CPU。 那些直接使用 bindprocessor 编程接口或者被 bindprocessor 命令外部绑定的程序必须能够处理处理器重分配。

当 CPU 已取消分配时被绑定到处理器的程序看到的主要问题是绑定到已取消分配的处理器的请求会失败。 发出 bindprocessor 请求的代码应该始终检查那些请求的返回值。

处理器重分配通知的接口

将线程绑定到最后绑定 CPU 的用户方式应用程序的通知机制与内核扩展的通知机制不同。

用户方式下的通知

将向绑定到最后一个绑定 CPU 的用户方式应用程序的每个线程发送 SIGCPUFAILSIGRECONFIG 信号。 这些应用程序需要修改以捕捉这些信号并(通过解除它们的绑定或者将它们绑定到不同的 CPU)处理绑定到最后绑定 CPU 的线程。

内核方式下的通知

必须通知即将发生的处理器重分配的驱动程序和内核扩展必须向内核注册高可用性事件处理程序 (HAEH) 例程。 当即将进行处理器重分配时,将调用此例程。 还提供接口在内核扩展被取消配置或者卸装之前注销 HAEH。

注册高可用性事件处理程序

内核导出新的函数以允许内核扩展通知以防发生影响系统可用性的事件。

系统调用为:
int register_HA_handler(ha_handler_ext_t *)

有关此系统调用的更多信息,请参阅 操作系统和设备管理中的 register_HA_handler

如果成功,返回值等于 0。 非零值指示发生故障。

系统调用参数是一个指针,指向描述内核扩展的 HAEH 的结构。 此结构如下定义在名为 sys/high_avail.h 的头文件中:
typedef struct _ha_handler_ext_ { 
    int (*_fun)();        /* Function to be invoked */ 
    long long _data;      /* Private data for (*_fun)() */ 
    char        _name[sizeof(long long) + 1]; 
} ha_handler_ext_t;

提供专用 _data 字段在需要时供内核扩展使用。 当由于发生 CPU 预测性故障事件而调用字段时,在注册时赋予此字段的任何值将被作为参数传递给已注册函数。

_name 字段为以 null 结束的最大长度为 8 个字符(不包括空字符终结符)的字符串,此字符串用来对内核唯一地标识内核扩展。 此名称在所有已注册内核扩展中必须是唯一的。 此名称列示在CPU_DEALLOC_ABORTED如果内核扩展在内核调用 HAEH 例程时返回错误,那么错误日志条目。

内核扩展应该仅注册它们的 HAEH 一次。

调用高可用性事件处理程序

下面的参数调用 HAEH 例程:
  • 被传递给 register_HA_handlerha_handler_ext_t 结构的 _data 字段的值。
  • 指向 sys/high_avail.h 文件中定义的 ha_event_t 结构的指针,如:
    typedef struct {                    /* High-availability related event */ 
        uint _magic;                    /* Identifies the kind of the event */ 
    #define HA_CPU_FAIL 0x40505546      /* "CPUF" */ 
        union { 
            struct {                   /* Predictive processor failure */ 
                cpu_t dealloc_cpu;     /* CPU bind ID of failing processor */ 
                           ushort domain;         /* future extension */ 
                ushort nodeid;         /* future extension */ 
                ushort reserved3;      /* future extension */ 
                uint reserved[4];      /* future extension */ 
            } _cpu; 
            /* ... */                  /* Additional kind of events -- */ 
            /* future extension */ 
        } _u; 
    } haeh_event_t;
函数返回下面的一个代码,它也在 sys/high_avail.h 文件中定义:
#define HA_ACCEPTED 0     /* Positive acknowledgement */ 
#define HA_REFUSED -1     /* Negative acknowledgement */

如果任何已注册扩展并不返回 HA_ACCEPTED,那么释放将异常终止。 HAEH 例程在进程环境中被调用且不需要被固定。

如果内核扩展取决于 CPU 配置,那么其 HAEH 例程必须对即将进行的 CPU 释放做出反应。 此反应高度依赖于应用程序。 要允许 AIX 继续执行取消配置,它们必须移动绑定到最后一个绑定 CPU 的线程 (如果有)。 而且,如果它们一直在使用从绑定线程开始的计时器,那么那些计时器将在 CPU 释放时被转移到另一个 CPU。 例如,如果它们与这些被转移给特定的 CPU 的计时器有任何相关性,在线程被绑定到新的 CPU 时,它们必须采取操作(例如停止它们)并重新启动它们的计时器。

取消注册高可用性事件处理程序

要保持系统一致和防止系统崩溃,注册 HAEH 的内核扩展必须在它们被解除配置并将被卸装时取消注册。 接口如下:
int unregister_HA_handler(ha_handler_ext_t *)

如果成功,此接口将返回 0。 任何非零的返回值都指示发生错误。

在测试环境中释放处理器

要测试在应用程序或者内核扩展中的任何修改是否支持此处理器重分配,请使用下面的命令触发释放由其逻辑 CPU 号指定的 CPU。 语法是:
cpu_deallocate cpunum

其中:

cpunum 是有效逻辑 CPU 号。

您必须重新引导系统,使目标处理器再次联机。 因此,仅为测试目的提供此命令,且并非为了用作系统管理工具。