0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用静态分析查找并发错误

星星科技指导员 来源:嵌入式计算设计 作者:Paul Anderson 2022-07-09 07:10 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

尽管几十年来小型化的进步已经为单处理器带来了巨大的性能提升,但这个时代似乎即将结束。使用单芯片实现显着额外性能的最佳选择是通过多个内核,但前提是软件可以编程以利用它们。

不幸的是,并发编程很困难。即使是只熟悉单线程编程的专家级程序员也常常无法理解并发程序容易受到诸如竞争条件、死锁和饥饿等全新类别的缺陷的影响。人类很难推理并发程序,并且编程语言本身的某些方面不适合并发。因此,专家们经常偶然发现这些危害。以下讨论描述了常见的并发缺陷,并解释了静态分析工具如何在不执行程序的情况下发现此类缺陷。

竞争条件的后果

当多个执行线程访问一个共享的数据并且其中至少一个线程在没有显式同步操作来分离访问的情况下更改该数据的值时,就会出现竞争条件。根据两个线程的交错,系统可能会处于不一致的状态。

种族条件特别阴险,因为它们可以无限期地潜伏而未被发现,并且只在极少数情况下出现,表现出难以诊断和重现的神秘症状。特别是,它们很可能通过对已部署软件的测试而存活下来。充其量,这意味着增加开发时间;在最坏的情况下,后果可能是毁灭性的。

2003 年东北大停电如此普遍的一个原因是计算机化能源管理系统中的竞争条件导致向运营商传达误导性信息。正如 Kevin Poulsen 在 2004 年的一篇文章 ( www.securityfocus.com/news/8412 ) 中指出的那样,“该漏洞有一个以毫秒为单位的机会窗口。” 在测试过程中出现此类问题的可能性微乎其微。在另一种情况下,iOS 4.0 到 4.1(现已修复)中的竞争条件意味着任何可以物理访问 iPhone 3G 或更高版本的人都可以在某些条件下绕过其密码锁定。

图 1 显示了一个简单竞争条件的示例。带有入口和出口传感器的制造装配线维护当前生产线上的项目的运行计数。每次项目进入行时,此计数都会增加,每次项目到达行尾并退出时,此计数就会减少。如果一个项目在另一个项目退出的同时进入该行,则计数应该递增然后递减(或反之亦然),以使净变化为零。但是,正常的递增和递减不是原子操作;它们由一系列单独的指令组成,这些指令首先从内存中加载值,然后在本地对其进行修改,最后将其存储回内存中。如果更新事务是在没有足够保护措施的多线程系统中处理的,由于传感器读取和写入共享数据:计数,因此可能会出现竞争条件。图 1 中的交错导致错误计数为 69。也有可能导致错误计数为 71 的交错,以及一些正确导致计数为 70 的交错。

图 1:竞争条件导致装配线上的项目计数不正确。

poYBAGLCrp6Ab6iLAAFNNb5eg0I645.png

对于这个例子和一般的竞争条件错误,标准调试技术可能由于几个原因而无效。

很少发生意味着发现问题的机会减少。如果问题不经常出现,它可能永远不会在测试期间出现。这个问题是双重的。首先,两个线程中可能的指令交错数量可能很大,并且随着指令数量的增加而急剧增加。这种现象被称为组合爆炸。如果线程 A 执行M条指令,线程 B 执行N条指令,则两个线程的可能交错为:

等式 1

poYBAGLCrqeANHacAAAxJkAc4zk487.png

例如,给定两个普通线程,每个线程有 10 条指令,则指令有 184,756 种可能的交错。现实世界的软件庞大而复杂;测试每一个交织是根本不可能的。其次,即使测试人员可以识别出一些值得检查的交错,也很难设置测试用例来确保它们确实发生,因为线程调度可能是高度不确定的。

如果详尽的测试难以解决,那么开发人员可以做什么?一种非常有用的方法是静态分析。CodeSonar 等高级静态分析工具使用高度复杂的符号执行技术同时考虑许多可能的执行路径和交错。这些技术可以在不需要执行程序的情况下找到竞争条件和其他并发错误。

有几个因素使比赛状况诊断变得困难。首先,症状可能令人困惑。在图 1 示例中,运行计数通常是正确的,但有时太高,有时太低。其次,不习惯考虑多线程编程的特定缺陷的程序员可能会在可能出现竞争条件之前花费大量时间对代码感到困惑。高级静态分析工具在这方面特别有用。他们通过检查共享内存位置的访问模式来识别竞争条件;也就是说,他们关注的是种族本身,而不是它的症状。当识别出竞争条件时,高级静态分析工具将报告它以及支持信息,以帮助用户进行评估和调试。程序员的负担大大减轻。

更复杂,更多错误

竞争条件通常通过使用锁来保护共享资源来避免。但是,锁可能会引入性能瓶颈,可能会阻止程序充分利用多核的潜力,因此程序员在使用它们时必须小心谨慎。编写有效使用锁的代码可能很棘手,这种复杂性可能导致一组不同的问题,即死锁和饥饿。

在死锁中,两个或多个线程相互阻止,因为每个线程都持有另一个线程需要的锁。图 2 显示了如何使用用于保护两个共享变量的两个锁出现死锁。在此示例中,多条装配线共享当前正在装配的项目总数,第二个 bad_items 值记录有多少成品未通过质量控制。一个线程在 count 上获得锁,另一个在 bad_items 上获得锁。两个线程都无法获得它需要的第二个锁;因此既不能执行它的操作,也不能到达释放锁的地步。由于两个更新都无法完成,因此两个线程都完全卡住了。

图 2:在两个线程之间的死锁中,两个线程都无法前进。

pYYBAGLCrq2Aad9iAAI2eenIfqA226.png

静态分析工具可以通过标记不同线程可以以不同顺序获取相同锁的情况来识别存在死锁风险的软件,例如图 2 中所示的线程。消除所有这些情况足以确保系统不会陷入死锁。

饥饿是使用锁的多线程程序中发生的另一个问题。如果一个线程正在等待另一个线程当前持有的资源需要很长时间,它可能会饿死。例如,假设上述制造自动化系统包括一个定期审核线程,该线程检查所有进入和退出记录,以确保运行计数与进入的项目总数相匹配,而退出的项目总数更少。审计线程需要锁定计数和所有传感器,因此所有更新都必须等待审计完成。如果审核运行很长时间,更新可能会显着延迟。如果运行时间过长,下一次审计可能会设法获取所有锁并在未完成的线程取得任何进展之前开始运行。在最坏的情况下,部分或全部更新可能永远没有机会运行。

静态分析可以通过提出诸如“在持有锁时是否调用长时间运行的库函数?”之类的问题来提供重要的价值。CodeSonar 等工具还为用户提供了添加自己检查的机制。如果已知内部函数 f() 具有较长的运行时间,工程师可以添加自定义检查,每当持有一个或多个锁的线程调用 f() 时触发警告。

多线程为嵌入式开发人员必须考虑的潜在错误添加了全新的类别,使得查找各种错误变得更加困难。最新一代的静态分析工具可以帮助解决这两个问题。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 传感器
    +关注

    关注

    2574

    文章

    54382

    浏览量

    786126
  • 嵌入式
    +关注

    关注

    5186

    文章

    20151

    浏览量

    328893
  • 计算机
    +关注

    关注

    19

    文章

    7764

    浏览量

    92688
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    C语言中除数为0属于什么错误

    在源程序的编写时往往会出一些错误,这些错误大致分为静态错误和动态错误两类。 所谓动态错误:逻辑
    发表于 12-08 06:38

    什么是CVE?如何通过SAST/静态分析工具Perforce QAC 和 Klocwork应对CVE?

    本文将为您详解什么是CVE、CVE标识符的作用,厘清CVE与CWE、CVSS的区别,介绍CVE清单内容,并说明如何借助合适的静态分析工具(如Perforce QAC/Klocwork),在软件开发早期发现并修复漏洞。
    的头像 发表于 10-31 14:24 285次阅读
    什么是CVE?如何通过SAST/<b class='flag-5'>静态</b><b class='flag-5'>分析</b>工具Perforce QAC 和 Klocwork应对CVE?

    分析负载特性时,有哪些常见的错误或误区?

    分析负载特性时,很多人会因 “想当然套用经验”“忽略实际场景细节” 或 “混淆概念” 导致判断偏差,进而让报警阈值调整失效(如误报、漏报)。以下是 6 个最常见的错误 / 误区,附错误表现、危害
    的头像 发表于 10-10 17:03 515次阅读

    国巨贴片电容的电压标识有哪些常见错误

    国巨贴片电容的电压标识在识别和使用过程中可能存在一些常见错误,这些错误可能源于标识本身的模糊性、不同系列产品的差异、对标识规则的误解,或使用环境的影响。以下是具体分析: 一、标识模糊或缺失导致的
    的头像 发表于 08-28 16:51 511次阅读

    知识分享 | 使用MXAM进行AUTOSAR模型的静态分析:Embedded Coder与TargetLink模型

    知识分享在知识分享栏目中,我们会定期与读者分享来自MES模赛思的基于模型的软件开发相关Know-How干货,关注公众号,随时掌握基于模型的软件设计的技术知识。使用MXAM进行AUTOSAR模型的静态
    的头像 发表于 08-27 10:04 495次阅读
    知识分享 | 使用MXAM进行AUTOSAR模型的<b class='flag-5'>静态</b><b class='flag-5'>分析</b>:Embedded Coder与TargetLink模型

    汽车软件团队必看:基于静态代码分析工具Perforce QAC的ISO 26262合规实践

    ISO 26262合规指南,从ASIL分级到工具落地,手把手教你用静态代码分析(Perforce QAC)实现高效合规。
    的头像 发表于 08-07 17:33 868次阅读
    汽车软件团队必看:基于<b class='flag-5'>静态</b>代码<b class='flag-5'>分析</b>工具Perforce QAC的ISO 26262合规实践

    动态BGP与静态BGP的区别?

    的 IP,只要远端发起 BGP 握手,且来自 AS 65002,即自动建立对等关系。四、实战应用场景分析场景一:传统运营商边界路由器 使用静态 BGP BGP 对等关系固定,变化极少 需要手动管理
    发表于 06-24 06:57

    鸿蒙5开发宝藏案例分享---应用并发设计

    ?** 鸿蒙并发编程实战指南:解锁ArkTS多线程黑科技** 嘿,开发者朋友们! 今天给大家扒一扒鸿蒙官方文档里藏着的并发编程宝藏—— 100+实战场景解决方案 !从金融理财到游戏开发,从折叠屏适配
    发表于 06-12 16:19

    RK3568驱动指南|第三篇-并发与竞争-第19章 并发与竞争实验

    RK3568驱动指南|第三篇-并发与竞争-第19章 并发与竞争实验
    的头像 发表于 02-24 16:26 851次阅读
    RK3568驱动指南|第三篇-<b class='flag-5'>并发</b>与竞争-第19章 <b class='flag-5'>并发</b>与竞争实验

    集成电路设计中静态时序分析介绍

    本文介绍了集成电路设计中静态时序分析(Static Timing Analysis,STA)的基本原理、概念和作用,并分析了其优势和局限性。   静态时序
    的头像 发表于 02-19 09:46 1305次阅读

    ADC的静态指标有专用的分析工具吗?

    请问:ADC的静态指标有专用的分析工具吗?该指标很少在评估ADC指标时使用,是否该指标不重要,应用中什么情况下需要评估该指标? 另外ADC的SNR = 6.02*N + 1.76 +10*log10(fs/2BW) 当被采样信号为单音时 该BW为多少?
    发表于 02-08 08:13

    基于Vector工具进行CAN协议错误帧的分析实践

    广播发送的短帧结构,还体现在其错误检测机制上。通过总线数据以及总线波形来分析总线故障时,CAN协议错误检测机制中丰富的错误帧类型能让定位问题的效率更高。
    的头像 发表于 01-15 10:03 998次阅读
    基于Vector工具进行CAN协议<b class='flag-5'>错误</b>帧的<b class='flag-5'>分析</b>实践

    电桥电路的常见错误分析

    电桥电路的常见错误分析主要包括以下几个方面: 一、电阻值不准确 电阻值不准确是电桥电路常见的错误之一。这可能是由于电阻本身的误差,如电阻的标称值与实际值存在偏差,或者电阻老化、温度变化等因素导致
    的头像 发表于 01-09 10:08 1943次阅读

    GPIO错误排查与解决

    在嵌入式系统和微控制器编程中,通用输入输出(GPIO)是最常见的接口之一。然而,在使用GPIO时,我们可能会遇到各种错误。 1. 理解GPIO GPIO是微控制器上的一组引脚,可以被配置为输入或输出
    的头像 发表于 01-09 09:46 3718次阅读

    RTOS中的错误检查机制

    在嵌入式应用中,有可能发生各种各样的错误,系统必须能够检测到这些错误并作出适当的响应。RTOS通常内置了一些错误检查功能,用于检测错误并向应用提供响应
    的头像 发表于 01-03 14:44 1022次阅读