APP下载

基于参数类型和访问序的数据冲突静态分析方法*

2019-01-22王小丽虞砺琨

空间控制技术与应用 2018年6期
关键词:子程序中断语句

董 燕,黄 晨,王小丽,虞砺琨,于 倩

0 引 言

嵌入式软件研制过程中,广泛采用中断服务机制来实现任务需求,但中断系统的设计和实现过程中很容易引入资源访问冲突错误.由于中断触发的随机性和不确定性,动态测试过程中难以发现和定位该类问题,造成软件相关的安全性可靠性测试降低,加大了软件维护成本,实践表明航天嵌入式软件后期测试发现问题至少50%为中断冲突问题[1].因此在软件设计及静态测试阶段进行中断冲突分析是十分有必要的.

目前,中断冲突技术及相关的工具的研究日渐增多[2-3],但是大多数还停留在理论研究阶段,实际进行应用的还较少,文献[4]重点针对单变量访问序模式,基于抽象解释,提出了一种支持过程间分析、中断并发分析的高效检测方法,但由于相关的冲突对象和场景识别不够充分和确定,导致在应用过程中存在信息误报率大,操作困难等实际问题[5-7].本文基于航天嵌入式软件近二十年第三方测试发现的中断冲突问题研究的基础上,识别和总结了中断访问冲突模式,并结合典型实例解析说明了冲突机理,对相关中断冲突场景和分析方法进行了较为全面的分析和总结.

1 中断访问冲突对象识别

中断访问冲突本质是对共享资源的访问存在竞争引起,因此识别竞争资源是冲突分析的首要步骤.竞争资源,也就是可能引入中断冲突的参数,包括任意一个变量,标准芯片端口、FPGA端口、绝对存储地址,这些参数只要在不同优先级的子程序中被引用,均是中断冲突分析对象[8-9].另外还有规定的软件固定操作序被软件其他操作意外打断的情况也有可能引入访问冲突问题.但对这些对象的访问并不是一定会引入中断冲突,具体在什么情况下会引入冲突还需要具体进行分析.

在此结合目前测试中已经发现的中断冲突问题,通过静态的分析参数类型及参数访问序,研究中断数据访问冲突及机理,继而形成静态的分析方法,能够有效弥补动态测试在发现数据访问冲突问题上具有随机性和不确定性的缺陷,提升发现数据访问冲突的准确率.

2 参数类型及冲突场景分析

依据处理器对参数的访问形式、多个变量之间的关系,将参数类型分为3类:

1) 原子变量

处理器对当前变量进行的一次读或者写访问时仅为单条语句,不存在被其他操作打断的可能.

2) 非原子变量

处理器对当前参数进行一次读或者写访问时必须分解为多条语句执行,比如数组变量(例如,char a[5]),多于处理器字长变量(例如,处理器8051机器字长为8 bits,软件定义int型变量对应16 bits).

3) 关联变量

两个或多个变量有依赖关系或者是同步关系,如一个数组中的多个元素拼接成为另外一个变量;一个变量是另外两个或几个变量的校验和;一个变量表示指令号与另一个变量表示指令内容一一对应.

2.1 原子变量冲突场景分析

可以较为容易理解的是,当处理器对变量的访问仅为一条汇编语句(一条汇编语句对应一个指令周期)时,即便是多个子程序同时对其进行访问,也不会存在因为变量内容不同步引入访问冲突问题,在此重点针对非原子变量、关联变量的典型冲突场景进行分析,说明冲突发生的机理和分析方法,后续不再针对原子变量进行访问冲突分析.

2.2 非原子变量冲突场景分析

该类型变量长度超出了对应处理器字长,虽然源代码级上只有一条语句,但编译后需要分成多条汇编语句步骤执行,下面以单片机8051和DSP TMS320C6000芯片为例,通过分析汇编代码验证中断冲突发生的场景.

8051为8位处理器(大端结构,低地址存高字节数据,高地址存低字节数据),定义变量c为int型(16位),则c对应2字节长度:

图1 单片机2字节变量冲突场景Fig.1 Conflict scene of single chip two bytes variable

上图1中一条给变量c赋值的C语言代码,对应的汇编代码为多条语句,分为先写入低字节数据,再写入高字节数据等多个步骤进行.

当主程序在写变量c两个字节过程中如果发生中断并进行读c的操作,此时读取到的c值高低字节数据并不同步.

TMS320C6000为32位处理器,定义变量a为long long int型(64位),对应2个字长度:

图2 DSP 2个字变量冲突场景Fig.2 Conflict scene of DSP 2 byte variable

图2中主程序中对变量a的赋值操作分为两步,先写低32位,再写高32位,如果在写操作过程中发生中断读变量a,会导致中断中读取到的变量a高低字数据不同步.

表1 Franklin C51的基本数据类型Tab.1 Basic data type of Franklin C51

嵌入式软件常用的芯片如MCS-51、SPARC、DSP处理器的字长分别为8位、32位和32位,为了辅助分析,针对不同的数据类型,给出对应的长度说明如表1~3所示.表1中的sfr是C51中定义特殊功能寄存器所使用的一种专用关键字,与标准C不兼容,只适用于C51.

表2 SPARC的基本数据类型Tab.2 Basic data type of SPAR

表3 DSP芯片数据类型Tab.3 Basic data type of DSP

注:“-”表示该芯片不存在当前数据类型.

2.3 关联变量冲突场景分析

当数组元素中的多个变量存在关联时,应保证相互关联变量读写操作的匹配性.

(1) 数组变量中的多个元素存在关联

在代码实现过程中,一般对数组变量的访问操作是由多条语句构成,对应的中断场景也最易识别,下面以实例进行分析:

参数:系统时间码System_time[6]:共6字节,前4字节为s,后2字节为ms;主程序对其进行读操作,中断服务子程序对其进行写操作,具体代码实现如图3所示:

图3 数组变量冲突实例Fig.3 Conflict scene of array variable

主程序一次读取系统时间码过程中发生中断进行时间写后返回,然后主程序继续读,读取到的时间码的3字节数据不同步.

(2) 多个独立的变量之间存在关联

例如:温度参数t1,t2,对应累加和变量t3,均为单字节变量.主程序读取t1,t2进行计算校验和,中断服务子程序读取t1,t2和t3进行遥测下行:

图4 关联变量冲突场景Fig.4 Conflict scene of related variables

上述图4变量如果独立分析,则均不会存在数据访问冲突,但由于t3与t1、t2存在一定的对应关系,则在代码设计过程中隐含的需求就是三者数据必须同步,否则当主程序读取t1、t2后计算t3之前产生中断,则遥测下行的t3与t1、t2不对应.

针对参数类型进行中断冲突分析时,除需要进行每个变量的类型分析外,还需要进行关联变量的识别,关联变量的识别应在软件研制过程中的需求分析阶段进行,在数据字典中进行明确定义.

2.4 参数类型冲突场景分析

针对多于处理器字长变量、数组变量、关联变量,一次读或写访问过程中可能引入数据访问冲突的场景及后果总结归纳如下:

(1) 主程序读—中断写,会导致主程序读取到的数据不同步;

(2) 主程序写—中断写,会导致主程序写入的数据值不同步;

(3) 主程序写—中断读,会导致中断读取到的数据值不同步;

(4) 主程序读—中断读,要针对具体情况分析是否存在不同步的可能,一般来说存在不同步的可能性较小.

3 参数访问序及冲突场景分析

以上是针对几种参数类型进行一次访问操作过程中引入的数据不同步场景分析.针对同一个参数的多次访问过程中,如果存在多次访问操作被中断打断的可能时,需要从参数访问序角度分析是否存在访问冲突.

3.1 参数访问序冲突场景分析

一个变量在主程序、各级中断服务子程序中多次进行读写,哪些会在读写过程中引入变量访问冲突呢,在此以中断中有读操作和写操作进行分类,并通过实例加以分析说明.

3.1.1 中断写操作时的主程序访问序

(1) 主程序中有读读操作序

图5代码针对变量rsCount的访问就是主程序进行连续两次读,中断服务子程序中进行一次写的操作.该种形式的访问序会在主程序第一条读语句执行后,第二条读语句执行前,如果产生中断,会导致第二次读出的数值与第一次不同.通过对本实例的分析,两条读语句对应的变量值应该为同一时刻的数值,上述代码存在访问冲突,在此称为“读读之间产生写”,通过该实例可以总结如下:

针对“读读之间产生写”访问序,分析是否发生中断冲突的途径就是确认两次或多次读语句对应该变量值是不是要求为同一时刻的值,如果要求是同一时刻的值,即多次读的过程中不能被中断改写,则该“读读之间产生写”访问序就存在中断访问冲突.

针对两次或多次读语句对应该变量值是不是要求为同一时刻的值,需要结合代码实现逻辑及软件功能进行测试需求分析,一般在同一个模块中连续读操作的访问冲突概率较大.

图5 主程序读-读操作序场景Fig.5 Main program reading reading-interrupt reading operation order

(2) 主程序中有读写操作序

从代码实现角度,针对读写访问序,体现为两种形式,多条源代码语句和一条源代码语句.

①多条源代码语句完成读写

多条源代码语句完成的读写典型过程如下图主程序部分,对应的冲突场景如下:

图6 主程序读写-中断写操作序场景Fig.6 Main program reading writing-interrupt writing operation order

针对图6形式的读写访问序,如果中断中写操作,则会在主程序读出变量a后,给a重新赋值之前,如果产生中断,则会造成中断给a赋值的操作被主程序的重新写覆盖,导致优先级高的程序功能写功能失效,即存在访问冲突.

②一条源代码语句完成读写

如c++,a=a+b.该类语句编译后对应的汇编代码通常均有多条语句组成,完成对应的读写操作.在此列出几种处理器8051系列,TSC695F及DSPTMS3206701对应的汇编语句如图7所示:

图7 一条源代码读写对应多条汇编代码实现Fig.7 Assembly code related to c source code

经分析汇编代码进行验证,针对单条的读写语句,对应的汇编代码均是先从原变量中读出原值到寄存器,在寄存器中完成运算操作,然后回写到原变量中,对应的访问冲突原理与多条语句完成读写相同,针对一条源代码读写操作存在访问冲突的场景,仅从源代码级别进行分析时无法发现冲突,需要翻译成对应的汇编代码进行分析,具体冲突场景如图8所示.

(3) 主程序中有写读操作序

写读操作序的访问流程如图9所示.

图8 主程序读写-中断写操作序场景Fig.8 Main program reading writing-interrupt writing operation order

图9 主程序写读-中断读操作序场景Fig.9 Main program reading writing-interrupt reading operation order

针对上述形式的写读操作序是否会引入访问冲突,需要结合代码实现逻辑,确认当前模块中对变量的读操作的来源:如果来源是当前模块内此前写入的内容,则该读操作应与前面的写操作不能被中断打断,否则会引入访问冲突;如果来源不限定本模块写入内容,则不会存在访问冲突.

(4) 主程序中存在只写操作

主程序和中断服务子程序均有写操作的变量,理论上会存在中断冲突导致中断的写操作失效,但此类冲突对软件功能是否有影响,需要结合功能背景及汇编代码进行影响分析,一般情况下这种访问序引起的中断冲突会造成软件错误.

3.1.2 中断读操作时的主程序访问序

(1) 主程序中有写写操作序

图10场景中,如果中断在第一次给TM[0]赋值语句后产生,则中断中读到的数据并不是本周期的最终结果,可能会导致后续操作错误.

主程序中有写写操作,中断中有读操作时,此时读取到的数据可能不是最终结果,导致功能实现错误.

图10 主程序写写-中断读操作序场景Fig.10 Main program writing writing-interrupt reading operation order

(2) 主程序中有其他操作序

当中断中存在读操作,主程序中存在读写操作、读读操作、写读操作的访问序时,需要根据中断中读操作时效性的要求进行分析,如果要求中断中读取到的是主程序中最新写入的数据,则可能存在数据访问冲突;如果不要求中断中立刻读取到主程序中最新写入的数据,则不存在数据访问冲突问题.

3.1.3 固定操作序冲突场景分析

固定操作序是指某项功能对应的一组固定执行动作,分布于一个或多个子程序中,涉及一个或多个变量,这些变量在当前固定动作中不能被外界意外改动.具体可分为一个子程序中的一个参数(端口)的固定操作序、多个子程序中的一个参数(端口)的固定操作序、多个子程序的多个参数(端口)的固定操作序等.在此以一个子程序中一个参数和多个子程序中一个参数为实例进行说明.

(1) 一个子程序中一个参数的固定操作序

以CAN控制器MCP2515通过SPI接口扩展方式的读操作过程对应一组操作序为例进行说明,向硬件端口的一系列操作如果被其他操作打断,会造成读操作失效.读操作序的基本过程如下:

1) CS片选拉低;

2) 往SPI数据端口写入命令0x03表示准备读数据;

3) 往SPI数据端口写入准备读出数据的对应地址;

4) 往SPI数据端口写入任意一字节数;

5) 从SPI数据端口读出数据;

6) CS片选拉高.

图11场景中当主程序进行读操作序过程中向芯片执行写入任意数0x55后,若发生中断进入写操作序,则在中断返回主程序后从SPI0DAT读出的数据不再是外部设备送入的内容,可能为中断服务子程序写入的值0x0EB,最终导致主程序中读出的不是预期内容,造成读操作失败.

图11 同一个参数固定读操作序冲突场景Fig.11 Conflicting scenario of reading sequence to the same parameter

(2) 多个子程序中一个参数的固定操作序

某嵌入式软件对OC门指令的输出操作过程为:向端口0x1111写入指令对应的编码0xXX以启动控制脉冲发送,持续20 ms±5 ms后,再向遥控端口0x1111写入0x00结束控制脉冲发送,如图12所示.

图12 向同一个参数写操作序冲突场景Fig.12 Conflicting scenario of writing sequence to the same parameter

为保证操作序的正常执行,分布于不同优先级子程序(主程序,定时器中断服务子程序)中的操作序不应被外界打断,但是该软件会发出不同种类的OC门指令.如果软件在启动20 ms定时后继续执行其他代码过程中再次满足发OC门指令且当前时间间隔小于20 ms,会重新执行主程序中定时20 ms操作,导致上一条OC门指令的执行过程被意外终止,即未在20 ms后发结束控制脉冲,输出的OC门指令高电平宽度不满足性能指标要求.

3.2 参数访问序冲突场景分析

针对某参数存在连续的多次访问操作序时,需要注意以下内容:

(1) 能够完成读写功能的一条源代码(如c++,a=a+b),如果中断服务子程序中有写操作,一定会引入该参数的访问冲突,导致参数数值错误;

(2) 一个参数在不同优先级子程序中均被访问时,针对低优先级子程序中的读写操作序如果不能被外界打断,当有高优先级子程序对其存在上述说明的访问时,一定会引入该参数的访问冲突,导致参数数值错误;

(3) 参数访问序的设置需要结合代码设计进行分析,确定其不可被打断的操作序有效范围,例如:多条语句构成的一个数学计算、一个独立的逻辑处理,后续参数访问应是依据前面访问逻辑获取的结果.

(4) 针对固定操作序,对应的操作序在执行过程中都不能被打断,如果被打断且高优先级程序中存在写操作会导致读操作失效.

(5) 固定的操作序可能分布于一个或多个子程序中,一旦启动后则不能因为任何其他外部条件意外终止,否则会导致操作序失效.

4 结 论

本文从参数类型及参数访问序两个角度对中断数据冲突进行了原理分析和方法研究.从参数类型进行分析:当主程序和中断中存在同时访问的共享参数资源是数组变量、多字节变量、关联变量时,当主程序或者中断中同时存在写操作时会造成数据不同步,存在访问冲突问题.从参数访问序进行分析情况会比较复杂一些,确保主程序中读写操作不会被中断改写;中断的写操作不会被主程序覆盖;中断中的读操作是最终结果,而不是中间计算过程;除此之外还有些情况需要结合具体应用背景进行分析.针对固定操作序,对应的操作序在执行过程中都不能被打断,如果操作序执行过程中,被高优先级子程序打断且对操作序中涉及的资源有写操作,则导致当前正在执行的固定操作序中所读数据不是当前操作序的结果,而是高优先级子程序操作序中的内容.如果操作序执行的过程中,存在新条件引起该操作序被重新启动,会导致当前正在进行的操作序被意外终止.

由于中断数据冲突的发生具有不确定性和随机性,文中描述的冲突场景不可能在所有的动态测试过程中都会出现,这种静态的分析方法相比较动态的测试更容易发现这种小概率随机性问题且容易实施,操作性较强.在软件设计和测试过程中增加专门的中断数据冲突分析有助于充分、全面、准确定位冲突问题,目前,这种分析方法目前已经应用于第三方实际测试过程中,并取得了较好的应用效果,发现了大部分中断冲突问题.本文列举的实例和分析方法有助于建立完善的缺陷模式库,在自动化检测工具中构建上述模型,可自动识别访问冲突问题.为自动化工具在检测数据竞争的准确性、高效性方面起到参考和借鉴作用.

猜你喜欢

子程序中断语句
数控加工中数控程序的简化
子程序在数控车编程中的创新应用
TMS320F28335外部中断分析与研究
多级中断屏蔽技术分析
一种考虑GPS信号中断的导航滤波算法
跟踪导练(二)(5)
在数控车床上加工软轴零件
我喜欢
冠词缺失与中介语句法损伤研究
作文语句实录