什么是Data Consistency?
吃完饭后不刷牙 Vehicle攻城狮 3月25日
导文
熟悉“吃完饭后不刷牙”的小伙伴,我这里应该不需要做过多介绍了,还不熟悉的速速将“汽车ECU设计”的公众号和“汽车控制器”的知乎专栏关注起来。
什么是Data Consistency?
要说明这个Data Consistency(数据一致性),我们首先举一个例子。如图有两个TASK,其中A的优先级高于B。A 每次给 X 增加 2,B 每次给 X 增加 1 。两个task 要执行读(step1),修改(step2),写(step3)的三步操作,则有可能出现下面这种情况:
-
假定X=5
-
TASK B执行读取(step1) X=5,并临时存储(堆栈或者MCU寄存器中)
-
TASK A 打断 TASK B
-
TASK A执行读,修改,写操作,将X=7写回RAM中
-
TASK A结束,继续执行TASK B
-
TASK B将之前临时存储的X(操作2)取出,并加1,将X=6写回内存
毫无疑问,其实我们期待的结果是,执行TASK A 和 TASK B 后得到 X=8。但是最终的结果是 X=6,TASK A的操作被丢失了。
可以看出,如果我们在软件设计中没有考虑数据一致性,就有可能因为操作系统的任务调度关系导致程序并没有按照期望的结果运行,严重时可能造成系统崩溃等意外状况发生。一般的,如果存在多段代码对同一数据内存进行访问时,就必须考虑到数据一致性可能带来的风险。正是由于此类问题往往难以排查,所以最好在开发初期的正向设计时就要考虑数据一致性的问题。
如何保证数据一致性?
顺序调度策略
将可能造成读写冲突的runables尽可能的放置在同一个task下顺序执行,这样每一个runable只能一个接着一个运行,数据一致性就可以得到保证。
The activation code of Runnables is sequentially placed in one task so that no interference between them is possible because one Runnable is only activated after the termination of the other. Data consistency is guaranteed.
加锁
如果读写冲突发生在很短的一段时间内,那么加上锁是一个简单的办法。在这期间,任何打断将不会被响应。
Interrupt blocking can be an appropriate means if collision avoidance is required for a very short amount of time. This might be done by disabling respectively suspending all interrupts, Os interrupts only or - if hardware supports it - only of some interrupt levels. In general this mechanism must be applied with care because it might influence SW in tasks with higher priority too and the timing of the complete system.
操作系统资源的使用
合理利用操作系统资源,可以使得高优先级代码将更少的受到锁带来的限制。然而缺点是这种方法将带来更复杂的访问机制,可能消耗更多的系统资源(代码量、MCU负荷增加)。
Usage of OS resources. Advantage in comparison to Interrupt blocking strategy is that less SW parts with higher priority are blocked. Disadvantage is that implementation might consume more resources (code, runtime) due to the more sophisticated mechanism. Appropriateness of this mechanism may vary depending on the number of OSs/cores and/or the number of available resources.
禁止相互任务抢占
将向受影响的任务分配相同的优先级、或将受影响的任务分配相同的内部OS资源或将其配置为非抢占任务来保证数据一致性。
Mutual task preemption is prohibited. This might be reached e.g. by assigning same priorities to affected tasks, by assigning same internal OS resource to affected tasks or by configuring the tasks to be non-preemptive. This mechanism may be inappropriate in multi-partitioned systems.
复制备份
复制备份可以说是目前解决数据一致性最好的方法之一,其核心思想:在Task被调用之前先对变量X,复制为X*,而在Task运行期间,process 对 X*进行处理操作,而在Task运行结束后,再将X*传递给X。通过这种机制,保证了在每个Task运行期间的X*都是独立的,不会因为任务优先级的不同而造成读写冲突,从而保证了数据的一致性。
Idea: The RTE creates copies of data items so that concurrent accesses in different task contexts cannot collide because some of the accesses are redirected to the copies.
参考资料:AUTOSAR_SWS_RTE.pdf