2. 常见故障模型:硬件故障、软件故障、人为故障

做可靠性验证,第一件事就是搞清楚——你到底在防什么?

我见过不少团队,一上来就堆测试用例,结果漏掉最基础的故障模式。说白了,你连敌人长什么样都不知道,怎么打?

这一章,咱们就把常见的故障模型掰开揉碎。我按自己的习惯分成三大类:硬件故障、软件故障、人为故障。你想想看,系统出问题,跑不出这三类。

核心观点:故障模型是可靠性验证的“靶子”。靶子画不准,后面的测试、分析、定位全是白费功夫。

常见故障模型分类框架 故障模型 硬件故障 软件故障 人为故障 开路 短路 漂移 内存泄漏 竞态条件 操作失误 说明:三类故障往往相互交织。比如硬件漂移可能导致软件竞态,人为误操作可能触发短路。 可靠性验证需要覆盖这三类,不能偏废。

2.1 硬件故障:开路、短路、漂移

硬件故障是可靠性工程的“老本行”。我入行那会儿,师父就跟我说:硬件不会无缘无故坏,一定有物理原因。

常见的硬件故障,归纳起来就三种:开路、短路、漂移。咱们一个一个说。

2.1.1 开路故障

开路,就是电路断了。电流过不去,信号传不到。原因很多:焊点脱落、线缆断裂、过流烧断、振动导致接触不良……

典型表现:功能完全丧失。比如电源开路,设备直接掉电;信号线开路,通信中断。

我的经验:曾经有一款车载控制器,出厂测试全过,但跑到客户手里就间歇性死机。查了两个月,最后发现是连接器端子压接工艺有问题,振动后偶尔开路。从那以后,我要求所有连接器必须做压接剖面分析。

2.1.2 短路故障

短路,就是不该连的连上了。电流走捷径,轻则功能异常,重则烧毁器件。

短路的原因五花八门:锡渣残留、绝缘层破损、潮湿导致漏电、金属异物掉入……

短路类型 典型场景 后果
电源短路 PCB 焊接桥连 烧保险、烧电源芯片
信号短路 排线相邻引脚粘连 数据错误、总线冲突
对地短路 电容击穿、绝缘破损 电平异常、功耗飙升

注意:短路故障的定位往往比开路更难。开路至少还能测通断,短路有时候是“软短路”——万用表量不出来,上电才现形。我建议备一台热成像仪,短路点通常会局部发热。

2.1.3 漂移故障

漂移,说白了就是参数变了。电阻值变大、电容容量衰减、晶振频率偏移、MOSFET 导通电阻增加……

漂移不像开路短路那么“暴力”,它是慢慢来的。今天还能用,明天性能下降,后天彻底失效。

为什么会这样?温度、湿度、老化、应力释放,都是元凶。

关键认知:漂移故障是可靠性验证中最容易被忽略的。很多产品出厂测试全合格,但用了半年后参数漂出规格,客户就投诉了。所以,高温老化测试和参数边界测试必须做。

2.2 软件故障:内存泄漏、竞态条件

软件故障,嗯,这话题我能聊一天。做了十几年系统,我最大的感受是:硬件故障往往有物理痕迹,软件故障纯粹是逻辑问题。

软件故障种类很多,但可靠性验证中最常碰到的,我挑两个重点讲:内存泄漏和竞态条件。

2.2.1 内存泄漏

内存泄漏,就是申请了内存不释放。一次两次没事,但跑久了,可用内存越来越少,最终系统崩溃。

我见过最典型的案例:一个嵌入式设备,运行 72 小时后必死机。查到最后,是某个中断服务程序里每次调用 malloc 但不 free。中断频繁触发,内存一点点被吃光。

// 典型的内存泄漏示例
void interrupt_handler(void) {
    char *buffer = (char *)malloc(256);
    // 处理数据...
    // 忘记 free(buffer);  // 泄漏就在这里
}

避坑指南:我曾经在一个项目中强制团队遵守“谁申请谁释放”原则,并且每次提交代码都要过静态内存分析。效果立竿见影,内存泄漏 bug 减少了 80% 以上。

2.2.2 竞态条件

竞态条件,就是多个任务同时访问共享资源,结果取决于谁先谁后。这种 bug 最难复现,也最难定位。

举个例子:两个线程同时写一个全局变量。线程 A 先读后写,线程 B 也先读后写。如果 A 读完之后、写之前,B 插进来写了,那 A 写回去的时候就把 B 的更新覆盖了。

// 竞态条件示例(伪代码)
int counter = 0;

// 线程1
void task1(void) {
    if (counter < 10) {
        counter++;  // 这里可能被线程2打断
    }
}

// 线程2
void task2(void) {
    if (counter < 10) {
        counter++;  // 这里可能被线程1打断
    }
}

注意:竞态条件的验证,靠常规功能测试基本没用。必须用压力测试和随机时序注入。我习惯在测试阶段故意把任务调度周期打乱,或者用多个 CPU 核同时跑,增加碰撞概率。

2.3 人为故障:操作失误

最后说人为故障。你可能会想:人又不是机器,出错很正常。但可靠性验证必须把“人”这个因素考虑进去。

人为故障,最常见的就是操作失误。比如:

  • 维护时接错线
  • 升级固件时断电
  • 配置参数填错
  • 维修后忘记装回屏蔽盖

我印象最深的一次:某通信基站批量掉线,查了三天,最后发现是现场工程师把光纤收发器的 TX 和 RX 接反了。你说这是硬件故障还是人为故障?

我的建议:可靠性验证中,一定要设计防呆测试。比如:接口做防反插设计、软件做参数合法性校验、操作流程做强制确认步骤。别指望人永远不出错,要假设“人一定会出错”,然后让系统扛得住。

2.4 三类故障的关联与验证策略

实际项目中,三类故障经常混在一起。硬件漂移导致软件时序异常,人为误操作触发短路……你很难孤立地看待它们。

故障类型 验证方法 定位手段
硬件开路/短路 边界扫描、ICT 测试、X-ray 检查 万用表、示波器、热成像
硬件漂移 高温老化、参数极限测试 数据趋势分析、统计过程控制
内存泄漏 长时间压力测试、内存监控 静态分析工具、堆栈跟踪
竞态条件 随机时序注入、多核并发测试 日志分析、断点调试
人为操作失误 防呆设计验证、操作流程评审 操作日志回放、故障复现

好了,这一章咱们把故障模型理清楚了。记住一句话:验证不是碰运气,是有的放矢。你知道敌人长什么样,才能设计出有效的防御手段。