作者 | strongerHuang

微信公众号 | 嵌入式专栏

在基于RTOS开发项目时,通常都会遇到互斥的情况,比如:几个任务都要使用一个UART串口进行发送数据。

如果不加互斥锁,优先级高的任务,会抢占串口并发送数据,则有可能会出现发送数据“乱码”的情况。

今天就说说在RTOS开发中,互斥锁一个常见的问题。

什么是Mutex互斥锁?

学习过RTOS的读者应该对互斥不陌生,互斥锁就是为了避免任务之间互相抢占某种资源而设计的一种“锁”。

就如上面说的,一个串口,被两个任务抢占,如果不加锁,则会出现两个任务交叉发送数据,即“乱码”;

但是,如果加了互斥锁,则会等待其他任务发送完成之后才继续发送,保证了数据的完整(而不是乱码);

Mutex互斥锁例子

这里以三个任务、两个互斥锁为例,代码如下:

void task1()
{/*do something*/OSMutex1_Pend();  //互斥锁1加锁/*加锁处理事情*/OSMutex1_Post();  //互斥锁1解锁
}void task2()
{/*do something*/OSMutex1_Pend();  //互斥锁1加锁OSMutex2_Pend();  //互斥锁2加锁/*加锁处理事情*/OSMutex2_Post();  //互斥锁2解锁OSMutex1_Post();  //互斥锁1解锁
}void task3()
{/*do something*/OSMutex2_Pend();  //互斥锁2加锁/*加锁处理事情*/OSMutex2_Post();  //互斥锁1解锁
}

这样设计,大家看出问题了吗?

老司机应该看出来了,新手可能摸不着头脑。

在任务2中,进行了2次加锁、解锁,而且“环环相扣”。

Mutex互斥锁问题

假如任务1、 任务2、 任务3优先级分别为:1、 2、 3。

优先级顺序就是:任务1 > 任务2 > 任务3(数字越小代表任务优先级越高)。

假设:任务1和任务2处于等待事件状态,也就是处于阻塞状态, task 3 处于运行状态

当任务3在“加锁处理事情”的时候,任务2抢占了任务3(任务2挂起时间到了),此时任务3挂起,任务2处于运行状态

如果任务2在“互斥锁1加锁”之后,任务1抢占了任务2,此时,任务1处于运行状态

这个时候,你发现问题了没有?

任务1在执行“OSMutex1_Pend();”会等待“互斥锁1解锁”,如果其他方式没有对“互斥锁1解锁”,则会出现“死锁”的情况。

分享一张图片,你就会明白什么是死锁了:

解决办法

比如对任务2加锁方式进行改善:

void task2()
{/*do something*/OSMutex1_Pend();  //互斥锁1加锁/*do something*/OSMutex1_Post();  //互斥锁1解锁OSMutex2_Pend();  //互斥锁2加锁/*do something*/OSMutex2_Post();  //互斥锁1解锁
}

或者对低优先级的任务3加锁方式进行改善:

void task3()
{/*do something*/OSMutex1_Pend();  //互斥锁1加锁OSMutex2_Pend();  //互斥锁2加锁/*加锁处理事情*/OSMutex2_Post();  //互斥锁2解锁OSMutex1_Post();  //互斥锁1解锁
}

出问题的原因, 当一个任务获得了临界区资源的锁,在没有释放这个锁的前提下又去获得另外一块临界区资源,这个时候就要引起足够的注意了,设计成败在于你是否彻底理解了之前的问题。

但是,归根到底这样的问题还是要求用户在设计阶段去避免,一个系统不可能是万能的,正确的设计才是最重要的。

------------ END ------------

点击“阅读原文”查看更多分享

RTOS 任务间互斥的难题相关推荐

  1. RTOS 任务间互斥的问题

    关注+星标公众号,不错过精彩内容 作者 | strongerHuang 微信公众号 | 嵌入式专栏 在基于RTOS开发项目时,通常都会遇到互斥的情况,比如:几个任务都要使用一个UART串口进行发送数据 ...

  2. Operating System-进程间互斥的方案-保证同一时间只有一个进程进入临界区(3)- TSL指令...

    本文接上一篇文章继续介绍如何实现同一时间只允许一个进程进入临界区的机制.本文主要介绍TSL指令. 方案汇总 屏蔽中断 锁变量 严格轮换法 TSL指令 Peterson解法 一.What is TSL ...

  3. ThreadX内核源码分析(SMP) - 核间互斥(arm)

    1.核间互斥介绍(_tx_thread_smp_protection) 在单核的ThreadX内核中,内核的临界资源互斥通过关中断实现:在多核cpu上,关闭整个cpu的代价比较大,单核上仍然使用关中断 ...

  4. Linux下的多进程间共享资源的互斥访问

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> ...

  5. linux-多任务同步和互斥

    文章目录 同步互斥概述 互斥锁 互斥锁的概念 互斥锁的操作 初始化互斥锁 互斥锁上锁 互斥锁解锁 销毁互斥锁 互斥锁案例 信号量 信号量的概念 信号量用于互斥 信号量用于同步 信号量的操作 信号量的初 ...

  6. [OS复习]进程互斥与同步1

    进程互斥与同步 1.引言:多道程序设计存在的问题? 采用多道程序设计技术的操作系统,允许多个进程同时驻留内存并发执行.思考: A.如何协调多个进程对系统资源,如内存空间.外部设备等的竞争和共享? B. ...

  7. 信号量、互斥体和自旋锁

    一.信号量 信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是共享内存方式的进程间通信.本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况.一般说来,为了获 ...

  8. 【Linux系统编程】进程同步与互斥:POSIX有名信号量

    在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量.无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥.它们的区别和管道及命名管道的区别类似,无名信号量则直 ...

  9. 互斥锁、条件变量、自旋锁、读写锁

    一.互斥锁 机制:一次只能一个线程拥有互斥锁,其他线程只有等待. 互斥锁是在抢锁失败的情况下主动放弃CPU,进入睡眠状态直到锁的状态改变时再唤醒,而操作系统负责线程调度,为了实现锁的状态发生改变时能唤 ...

最新文章

  1. es6箭头函数(=)与展开特性运算符(...)的使用
  2. java多线程面试_面试之JAVA多线程
  3. git 撤销刚才的rebase_git rebase 的使用 (用于撤销某次commit)
  4. 函数失败返回_为什么句柄返回值不一致?
  5. AQS理解之六,AQS的其他实现类
  6. 经典C语言程序100例之七四
  7. 杭电2035--人见人爱A^B
  8. C#实现Web文件的上传
  9. 给网游写一个挂吧(三) – 启动外挂下
  10. 初识ABP vNext(11):聚合根、仓储、领域服务、应用服务、Blob储存
  11. JDK 11:轻松取出单文件Java源代码程序
  12. ulli*3 实现翻书动画效果
  13. java 线程内存模型_JAVA内存模型与线程
  14. 搜索文献_搜索参考文献?6个搜索小技巧,搞科研需知!
  15. 从“三只小猪”的故事到“高性能”测试自动化
  16. 解析Hibernate中的持久化—ORM
  17. sqlserver修改实例名
  18. 小技巧:Windows快捷键快速打开程序
  19. 抖音小程序服务器域名,抖音小程序使用场景、3大入口详细介绍
  20. flex属性-flex:1到底是什么

热门文章

  1. div 超出高度滚动条,超出宽度点点点
  2. 福州联通与市政府携手 共筑新型智慧城市
  3. http协议工作流程
  4. 明日之后怎么跳过实名认证_明日之后宝箱达人活动怎么玩 明日之后宝箱达人可以开箱多少次...
  5. 背景宽高随文本变化_中科大提出ContourNet:更准确的任意形状场景文本检测新方法...
  6. 深度学习之非极大值抑制(Non-maximum suppression,NMS)
  7. 深度学习之 hard negative mining (难例挖掘)
  8. mac安装完mysql后关机特别慢_mysql-Mac终端下遇到的问题总结
  9. celery AttributeError: 'str' object has no attribute 'items'
  10. HDFS读写数据的原理