良许Linux教程网 干货合集 嵌入式环境下并发控制与线程安全

嵌入式环境下并发控制与线程安全

随着代码规模的增长以及基于RTOS的多线程技术的应用,嵌入式软件开发越来越注重”并发控制和线程安全”。当多个执行线程(指正在运行代码的任意上下文,包括线程和中断服务程序)需要访问相同的共享资源时(包括软件数据和硬件资源),就有可能因为竞态而引发错误。

这种错误很容易发生,但很难被发现,在设计阶段确保正确性带来的收益更大。

竞态错误的产生

当多个执行线程以”非原子”的方式访问共享资源时,一个执行线程的操作可能会被另一个执行线程打断,从而引发竞态错误。共享资源可以是硬件设备或软件实体。

最明显的共享资源是全局变量。如果定义了一个数组,并且多个线程对其进行读写操作,那么这将成为最容易理解的竞态情况。

int g_aiGlobalBuf[100];

另一种不太明显的共享是由不可重入函数造成的,如果多个线程调用了下面的函数,那么同样产生竞态。

void ProcGlobalBuf(int iPos, int iVal)
{
  g_aiGlobalBuf[iPos] = iVal;
}

硬件资源被多个线程使用也会引入竞态,如下面的函数(使用伪代码)被2个线程同时调用,那么第一个线程的数据可能还没有发送完毕就被第二个线程的数据“覆盖”。

void SendByDMA(const void *p_vBuf, int iSize)
{
    DMA.StartAddr = p_vBuf;
    DMA.Count = iSize;
    EnableDMA();
}

一句话:任何被多个执行线程使用的资源都可能产生“竞态”。

并发控制规则

规则一:只要可能,就应该避免资源的共享。

如果没有并发访问,就不会有竞态的产生。因此,设计代码应该具有最少的共享。这种思想的最明显应用是避免使用全局变量。如果我们将资源放在多个执行线程都会找到的地方,则必须有足够的理由。

例如硬件资源的分配中,串口只能由线程1调用,网口只能由线程2调用,LCD只能由线程3调用,那么这3种硬件资源的竞态一开始就杜绝了,同理可以应用到软件资源上。

规则二:引发竞态的共享资源必须加锁

然而,在计算机的世界里共享就是现实的生活,在单个执行线程之外共享硬件或软件资源的任何时候,因为另外一个线程可能产生对该资源的不一致观察,就必须显示地管理对该资源的访问。

像只读数据(如芯片的序列号)对于任何访问它的执行线程看来都是一致的,那么竞态是不可能发生的。

基于RTOS的嵌入式环境下对共享资源的加锁一般有3种途径:关中断、使用信号量、禁止任务切换。

关中断应用于2种情况:如果任务代码和中断程序共享资源,或者共享资源访问时间很短(如操作一个变量);如果仅线程之间访问一些共享资源且操作时间不太长,禁止任务切换可以胜任;其他情况下都将使用信号量。

规则三:被多线程调用的函数必须是可重入

一个函数是否是可重入的判断规则:

一个可重入函数一般用原子的方法使用变量,除非这些变量存储在调用这个函数的堆栈中或这些变量是任务的私有变量。

一个可重入函数一般不调用其他的不可重入的函数。

一个可重入函数一般不用非原子的方法使用硬件。

锁的使用规则

当我们创建一个可被并行访问的对象时,应该同时定义用来控制访问的锁。锁定模式必须在一开始就安排好,否则其后的改进将会非常困难。

如果某个获得锁的函数要调用其他同样试图获取这个锁的函数,我们的代码就会死锁,即不允许锁拥有者第二次获得这个锁;如果试图这么做,系统将持起。

提供给外部调用的函数必须显示地处理锁定,在编写那些假定调用者已处理了锁定的内部函数时,我们自己应该显示地说明这种假定,否则几个月后再回头来看这些代码时,很难记清在调用某个特定函数时是否需要拥有锁。

尽可能避免出现需要多个锁的情况,实在需要多个锁就要防止死锁的发生:始终以相同的顺序获得锁,并且了解其他代码操作锁的做法;先获取自己局部锁,再获取其他锁;在拥有锁时尽量避免线程被挂起,那样会导致实时性下降,甚至永久性挂起系统。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部