C 和 C++ 在某种程度上是嵌入式软件开发中使用最广泛的语言。VDC 最近的研究表明,70% 的受访嵌入式系统公司使用 C,42% 使用 C++。几乎每个处理器都实现了 C。它提供了广泛的资源和库,并得到了广泛的工具的支持。
尤其是 C 语言,允许开发人员做许多本质上不正确的事情。编写符合语言标准的代码太容易了,但会导致程序失败(崩溃)或未定义的行为。常见的示例是导致访问数组边界之外的内存的代码或导致整数溢出的算术运算。
编码标准的哲学
业界接受的解决这些危害的方法是采用“编码标准”。最简单的编码标准定义了一组一致的编码实践。尽管风格的统一性在软件项目中可能很有价值,但它们并没有解决软件质量的重要属性,例如可靠性、可移植性或可维护性。编码标准更基本的作用是通过制定一组规则来定义编程语言的更安全的子集,以消除已知危险的编码结构。
体现这一安全子设置原则的汽车工业软件可靠性协会 (MISRA) 编码指南现已在全球范围内被公认为用 C 和 C++ 开发安全关键型软件的基准。它们已被广泛接受,因为它们简洁易读,并且专注于基本问题。最近一项针对 500 名受访者的民意调查 (Ganssle, 2014) 揭示了一些关于编码标准采用率的有趣数据[1]。主要发现表明,在使用的所有编码标准中,约有 60% 是基于 MISRA 的。采用的严格性是另一个有趣的发现,基于 MISRA 的编码规则集在开发团队中实现了 75% 的一致性使用,而其他规则集的使用率不到 50%。
偏差原理
MISRA 编码标准包含广受推崇的 C 和 C++ 语言开发指南。这些指南侧重于开发关键软件系统时的重要问题。MISRA 还认识到,在某些情况下,遵守编码指南是不合理甚至不可能的,并且有必要偏离某些规则。偏差说明了在特定情况下不遵守特定编码规则的原因。它还提供了放宽特定规则的程度的理由和描述,并提供了一个适当构建的安全案例,包括减轻不遵守的影响。
但是,如果没有仔细说明违规范围,基本偏差工具可能会被误解或滥用,并最终破坏指南的有效性。
限制偏差的使用
就像编码标准本身需要客观的创造和充分理解的理由一样,偏离编码规则的原因同样需要一个共同的表达和商定的解释以及它们的应用范围。汽车行业是 MISRA 最初且仍处于领先地位的应用领域,它已面对这一要求。MISRA 本身和一个国家机构日本汽车制造商协会 (JAMA) 都已开始制定允许特定偏离完全 MISRA 合规性的条件的过程。
这项工作的主旨是定义一组严格限制范围的规则偏差。一个重要的第一阶段是对偏离规则不合规的广泛原因进行分类。
分类偏差原因
通过将偏差分为以下几类,合规的实际困难变得更加明显。此外,这种分类可以防止不适当的偏差和编码标准意图的弱化。
表现
建议将性能作为不遵循良好编码实践的原因似乎很奇怪且不直观,但以下现实生活中的情况证明了这种需要:
作为车辆发动机控制系统的一部分,需要定期累积正时变量。该代码经过正确制定以符合 MISRA-C:2012 规则 10.6(不应分配给更广泛类型的值),内容如下:
extern uint16_t 数量,time_step;uint32_t prod = (uint32_t) 数量 * (uint32_t) time_step;
强制转换确保 16 位操作数不会在此编译器的 32 位乘法中溢出。但是,编译器使用长乘法的“移位和加法”模式而不是它配备的 IMUL(有符号乘法)模式来执行此操作。编译器供应商已澄清 IMUL 模式仅发生在隐式转换上,要求表达式读取:
uint32_t 产品 = 数量 * 时间步长;// 偏离规则 10.6
通过在这种情况下允许隐式转换,保证了单个时钟周期的 IMUL 操作,而不是前者的约 100 个时钟周期的最坏情况执行,从而证明了基于性能的受控偏差是合理的。
外部(第三方)代码
此类别包括通用库、自动生成的代码和遗留的内部代码模块,甚至只是包含关键应用程序算法的复杂函数。公共领域库的维护者,鉴于其广泛的应用领域,很少有动力遵守 MISRA 或其他编码标准。自动生成的代码,除非符合 ISO 26262 等功能安全标准,否则可能包含固有的 MISRA 违规。遗留代码可能早于项目采用 MISRA。为满足 MISRA 规则而进行的可能重构的影响分析本身可能会引起关注。所有这些情况下的安全案例都是基于“使用合格”的依赖以及其他特定的质量措施。
构建配置
汽车供应商应用程序的一个特殊功能是根据客户需要提供单个代码库的许多变体。不是对这种交付进行构建级控制,而是部署配置机制来控制每个变体的功能交付。因此,MISRA 合规性可能会在冗余代码、表达式不变性和相关的全局问题方面受到影响。
访问硬件
为了访问寄存器、寻址绝对内存和控制中断,嵌入式开发人员需要访问特定于编译器的 C 语言扩展,从而导致不符合 MISRA。安全案例通常需要仔细的单元测试覆盖。
防御性编码
鉴于 C 语言中缺乏强大的异常处理功能,防御性编码实践可能涉及例如对不可预见行为的编程防护。一个功能齐全的分析工具将正确检测不变的条件和无法访问的代码。安全案例必须涉及这些路径或条件的强制单元测试执行。
语言特点
使用“最近的”语言结构有有效的代码质量原因,例如布尔或“long long”类型或内联函数。但是,这些可能需要偏离旧版本的 MISRA。安全问题是即使有 15 年历史的 C99 结构也不能保证得到所有编译器的支持。
受控偏差的结构
对不同的基本原理进行分类是创建适当约束的偏差结构的第一步。这自然会导致按规则和类别详细说明所有特定的已知偏差案例。MISRA 和 JAMA 都在行业参与的情况下记录了一组规则范围限制,每个限制都有详细的理由和安全案例。
即使在汽车领域之外,这些举措也很重要。MISRA 编码标准最初是为汽车行业设计的,但从早期开始,它就被许多其他嵌入式环境所采用,从消费产品到医疗设备,从工业控制到 EDA。同样,对于任何采用编码标准的人来说,建立一个受控偏差结构都很重要。
自动化工具支持
没有自动执行手段和丰富的审计和报告能力的编码标准将很快成为书柜的装饰品,很少被引用或遵循。一个称职的自动化静态分析工具的起点必须是其诊断输出的准确性、对所提出的每个问题的清晰理解和解释,以及针对软件项目的每个版本的详细报告。
但即使是自动化工具执行环境也需要了解和应用已批准的偏差政策,特别是因为这消除了完全合规的障碍。编码规则和偏差策略都必须方便开发人员、领导和经理信任,并便于详细的 QA 报告。
基本偏差系统会将规则抑制的每个实例与其支持偏差耦合,并在相关源代码的生命周期内保持这种耦合(图 1)。在处理受控偏差时,要求更加复杂。对相关编码规则的任何压制都必须遵守更严格的有效限制,并且在该受控偏差集之外不得进行压制。在选择要抑制报告诊断的特定代码位置时,必须限制开发人员仅使用允许的受控偏差范围进行抑制。
图 1:受控偏差的工具执行。
关键系统的安全代码
MISRA C 编码标准是在许多嵌入式环境及其他环境中安全和防御性使用 C 的代名词。由于在 C 语言的限制使用方面既全面又广泛,控制偏差的系统现在被认为是必要的,正如各种行业和社区为指定这种缩减所做的努力所证明的那样。现在正在为工业用途制定合理的具体偏差原因。对受控偏差计划的复杂和自动化工具支持以及报告和合规解决方案的其他元素今天可用。
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !