精华内容
参与话题
问答
  • 互斥信号量与信号量的理解

    千次阅读 2018-09-17 10:10:24
    ucos看了也有一周多了,索性源码都能开得懂,并且能去理解。昨天一开始看事件标志组的时候确实不知道怎么回事,后来百度一下,明白了事件标志组的作用以后,再去看书上的讲解和原码就清晰多了,很容易就明白了他的...

    ucos看了也有一周多了,索性源码都能开得懂,并且能去理解。昨天一开始看事件标志组的时候确实不知道怎么回事,后来百度一下,明白了事件标志组的作用以后,再去看书上的讲解和原码就清晰多了,很容易就明白了他的基本运行机理。这也给了我一点启示,学一个东西,看一个东西之前,你最少要知道他干嘛用的,如果连干嘛用的都知道书看的再熟也是枉然。
        ucos中提供了好几个用于同步事件以及共享资源访问的机制,目前我看明白的有信号量,互斥信号量,事件标志组。下面谈谈自己对他们的理解:

    1.互斥信号量:
    互斥互斥,意思就是我用了你就不能用,你用了我就不能用。永远都只有一个人独占这个东西~!举个例子:比如说打印机。
    我任务1现在让他打印《静夜思》,那么在我还没打印完之前,别的任务就不能命令打印机去打印别的东西。否则如果任务2让他打印《春晓》,那最后打印出来的会是什么~????反正肯定不是任务1想要的,肯定也不是任务2想要的。
    上面讲的比较通俗。打印机就是共享资源,谁都可以访问他~!但是同一时间,肯定要保证只有1个任务再操作打印机。那样才能得到大家想要的结果。也就是要独占共享资源的访问权~!

    ucos2中通过互斥信号量来解决这个问题。简单说就是任务1开始访问打印机的时候,先去查询这个互斥信号量是否有效,有效,说明没人在访问打印机,这时任务1就把这个互斥信号量置无效,然后开始操作打印机。这样,每个任务再操作打印机前都要去查询这个互斥信号量时候有效。无效就等,等到有效才可以访问,或者等到不耐烦了(术语叫等待超时)就不等了~!任务一直到用完了打印机后才把信号量置有效,这时其他任务才有可能去访问,操作打印机。

    这里又有一个问题:再任务1操作打印机器件,可能有多个任务申请打印机的所有权。那么再任务1结束后,我应该给谁用呢~~??也许我们马上就反应过来了~废话~!!当然是排队了~~谁先到的谁用啊~~~。没错,这是一种机制,谁最先等待共享资源,就给谁用。但是~!再ucos里面2.52版本还不支持这种方式。他用的另外一种方法!如果你和你BOSS都再等着用打印机,你先到的,这个时候任务1结束了对打印机的操作。你说你敢先用么~???(除非你第二天不想干了~~)你肯定先让老板先用,这就是ucos的实现方式,基于优先级,任务1结束对打印机的操作后,ucos再等待队列中看那个等待任务优先级最高,就先给他用~!即使他是最晚才等待的~!!(这就是BOSS的威力~!)
    关于事件等待列表,有兴趣的可以去看看事件控制块ECB的内容,不在本文讨论。当然,ucos中的互斥信号量还有许多要素,比如说他的继承优先级之类的。本文旨在说明它是干嘛用的,至于其他请参考相关书籍。
    下面的图解释了互斥信号量的基本用法:(简单的两个任务,没有包含多任务等待的情况)
     
    2.信号量:
        至于信号量,和互斥信号量是用区别的,简单来说(个人理解,欢迎纠正)就是互斥信号量再同一时刻,任务得到互斥信号量量后是独占共享资源的,在他没有释放信号量之前,任何其他任务都是不能访问共享资源的。而信号量的不同在于。信号量可以设定一个值,允许最多又几个任务同时去访问共享资源。比如我给他设定一个5,那么对多就有5个任务能同时访问共享资源。每个任务获得信号量的时候就把信号量计数器减去1,这样,再第五个任务获取后,计数器是0.当第六个任务要去访问的时候申请信号量就只能等待了,等到之前的任务发一个信号出来,这样第六个任务才能去访问共享资源。

    互斥信号量可以看成特殊情况下的信号量,他的计数器就是0或者1,只在这两个之间徘徊。
    举个例子(不一定恰当,欢迎纠正):
    现在有很多串口扩展卡,一张卡能扩展出好几个串口,比如说4个,这个扩展卡就是一个共享资源。现在定义一个信号量semcom,初始给他4,那么可以有4个任务去访问这个资源,他每次就给这4个任务分配不同的串口。每个任务要访问这个扩展卡就要去测试semcom看看他时候有信号。这样,前4个任务申请信号后,信号量计数器就等于0了,这样,在第五个任务要去访问扩展卡的时候,他也去测试这个semcom,发现信号量无效,他只能等了~!等到之前的任务释放一个串口为止,如果不用信号量,那么任务五可能就会去访问扩展卡上的串口1,而串口1之前已经分配给了任务1了,~造成什么后果就自己想想吧~~~~如果用互斥信号量,那么无疑浪费了资源,~~~那你就买个扩展1个串口的卡就行了~~你买个扩展4个的然后你用互斥信号量~~~不是摆明再说你是富二代么~~~
    等待信号的任务在有信号以后也是按照等待列表中优先级最高的任务先得到信号处理。有关信号量的具体数据结构参考事件控制块ECB的内容,具体操作参考信号量函数等。在此不做介绍
    下面这个图说明了以上的例子:(有图有真相~!)



    3.事件标志组:
        在理解信号量和互斥信号量的时候都可以类比,因为他们在ucos2里面都通过相同的时间控制块即ECB这个数据结构来实现,理解了一个就很好能看懂另外一个,设置更后面的邮箱和消息队列,也能和信号量之类的类比来学习,他们都有通过ECB来维护。但是事件标志组比较特别,他是ucos2所有这些内核事件里面没有用到ECB的。他有自己的做法。不太合群。什么是事件标志组?
        上面说的信号量,互斥信号量。都是用来同步任务对共享资源的访问,防止冲突而设立的。事件标志组----他是用来同步几个任务,协调几个任务工作而设立的。打个比方你现在要打个电话,打电话这个任务要执行,你必须有手机吧!那你要先执行买手机这个任务,你手机有了,没话费~你也大不了吧~,也就是说打电话这个任务要等买手机这个任务和充话费这个任务都完成了以后你才能去开始打电话这个任务。事件标志组就是用来标志买手机或者充话费这两个任务完成了没有。完成了的话他们会相应的置位事件标志组里面的某些标志位。那么打电话这个任务。发现事件标志组里面买手机对应的位和充话费对应的位都置位了以后就明白,现在可以开始打电话了~!实际中比如你想要读数据,那你肯定要等数据采集更新好了以后你去读才有意义吧~所以数据采集和读取数据这两个任务也可以用事件标志组来实现。当然,事件标志组不一定只用于两个任务之间,通过对头文件的修改,可以让事件标志组达到32位,你可以用事件标志组来协调多个任务的合理运行。达到你预期想达到的目的!事件标志组就是专门干这个活的。
        事件标志组的结构比其他的会复杂一点。没一个事件标志组都维护这自己的一个等待队列的双向链表。每个事件标志组的节点里面都有一个指针和相应的任务控制块TCB一一对应。至于事件标志组的具体实现方法,可以自己去看看源代码。只要
    懂得一些浅显的双向链表的知识,大概理解他的运作机制不会很难。
       

     

    互斥信号量:只有一个线程独占资源,其他子任务在访问资源时需要判断信号是否满足,不满足则等待;

    信号量:同时满足多个任务执行,当超过这个信号量个数时,其他任务需等待。

     

    展开全文
  • 互斥量表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。   Mutex本质上说...

    互斥量(Mutex)

     

    互斥量表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。

    clip_image001

     

    Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥。Mutex对象的值,只有0和1两个值。这两个值也分别代表了Mutex的两种状态。值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待;值为1,表示空闲状态,当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0。

    Mutex可以被抽象为四个操作:

    - 创建 Create

    - 加锁 Lock

    - 解锁 Unlock

    - 销毁 Destroy

    Mutex被创建时可以有初始值,表示Mutex被创建后,是锁定状态还是空闲状态。在同一个线程中,为了防止死锁,系统不允许连续两次对Mutex加锁(系统一般会在第二次调用立刻返回)。也就是说,加锁和解锁这两个对应的操作,需要在同一个线程中完成。

    不同操作系统中提供的Mutex函数:

    动作/系统

    Win32

    Linyx

    Solaris

    创建

    CreateMutex

    pthread_mutex_init

    mutex_init

    加锁

    WaitForSingleObject

    pthread_mutex_lock

    mutex_lock

    解锁

    ReleaseMutex

    pthread_mutex_unlock

    mutex_unlock

    销毁

    CloseHandle

    pthread_mutex_destroy

    mutex_destroy

     

     

    死锁主要发生在有多个依赖锁存在时, 会在一个线程试图以与另一个线程相反顺序锁住互斥量时发生. 如何避免死锁是使用互斥量应该格外注意的东西。

      总体来讲, 有几个不成文的基本原则:

      对共享资源操作前一定要获得锁。

      完成操作以后一定要释放锁。

      尽量短时间地占用锁。

      如果有多锁, 如获得顺序是ABC连环扣, 释放顺序也应该是ABC。

      线程错误返回时应该释放它所获得的锁。

     

    也许还有读者好奇,“挂起等待”和“唤醒等待线程”的操作如何实现?每个Mutex有一个等待队列,一个线程要在Mutex上挂起等待,首先在把自己加入等待队列中,然后置线程状态为睡眠,然后调用调度器函数切换到别的线程。一个线程要唤醒等待队列中的其它线程,只需从等待队列中取出一项,把它的状态从睡眠改为就绪,加入就绪队列,那么下次调度器函数执行时就有可能切换到被唤醒的线程。

     

    一般情况下,如果同一个线程先后两次调用lock,在第二次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此就永远处于挂起等待状态了,这叫做死锁(Deadlock)。另一种典型的死锁情形是这样:线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都永远处于挂起状态了。不难想象,如果涉及到更多的线程和更多的锁,有没有可能死锁的问题将会变得复杂和难以判断。

     

    信号量

    信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

    信号量可以分为几类:

    ² 二进制信号量(binary semaphore):只允许信号量取0或1值,其同时只能被一个线程获取。

    ² 整型信号量(integer semaphore):信号量取值是整数,它可以被多个线程同时获得,直到信号量的值变为0。

    ² 记录型信号量(record semaphore):每个信号量s除一个整数值value(计数)外,还有一个等待队列List,其中是阻塞在该信号量的各个线程的标识。当信号量被释放一个,值被加一后,系统自动从等待队列中唤醒一个等待中的线程,让其获得信号量,同时信号量再减一。

    信号量通过一个计数器控制对共享资源的访问,信号量的值是一个非负整数,所有通过它的线程都会将该整数减一。如果计数器大于0,则访问被允许,计数器减1;如果为0,则访问被禁止,所有试图通过它的线程都将处于等待状态。

    计数器计算的结果是允许访问共享资源的通行证。因此,为了访问共享资源,线程必须从信号量得到通行证, 如果该信号量的计数大于0,则此线程获得一个通行证,这将导致信号量的计数递减,否则,此线程将阻塞直到获得一个通行证为止。当此线程不再需要访问共享资源时,它释放该通行证,这导致信号量的计数递增,如果另一个线程等待通行证,则那个线程将在那时获得通行证。

     

     

    Semaphore可以被抽象为五个操作:

    - 创建 Create

    - 等待 Wait:

    线程等待信号量,如果值大于0,则获得,值减一;如果只等于0,则一直线程进入睡眠状态,知道信号量值大于0或者超时。

    -释放 Post

    执行释放信号量,则值加一;如果此时有正在等待的线程,则唤醒该线程。

    -试图等待 TryWait

    如果调用TryWait,线程并不真正的去获得信号量,还是检查信号量是否能够被获得,如果信号量值大于0,则TryWait返回成功;否则返回失败。

    -销毁 Destroy

    信号量,是可以用来保护两个或多个关键代码段,这些关键代码段不能并发调用。在进入一个关键代码段之前,线程必须获取一个信号量。如果关键代码段中没有任何线程,那么线程会立即进入该框图中的那个部分。一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。

    动作/系统

    Win32

    POSIX

    创建

    CreateSemaphore

    sem_init

    等待

    WaitForSingleObject

    sem _wait

    释放

    ReleaseMutex

    sem _post

    试图等待

    WaitForSingleObject

    sem _trywait

    销毁

    CloseHandle

    sem_destroy

     

     

     (生产者 消费者)

     

     

     

    互斥量和信号量的区别

    1. 互斥量用于线程的互斥,信号线用于线程的同步。

    这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。

    互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

    同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源

    2. 互斥量值只能为0/1,信号量值可以为非负整数。

    也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。

    3. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。

    展开全文
  • 信号量和互斥信号量的理解

    千次阅读 2019-04-09 08:26:11
    信号量和互斥信号量的记住和理解应用是不一样的哦,面试常问。 做下本人理解和参考他人后的笔记 对于互斥锁(Mutex)来说,只要有线程占有了该资源,那么不好意思,其他线程就是优先级再高,您也得等着,等我用完...

    信号量和互斥信号量的记住和理解应用是不一样的哦,面试常问。
    做下本人理解和参考他人后的笔记

    对于互斥锁(Mutex)来说,只要有线程占有了该资源,那么不好意思,其他线程就是优先级再高,您也得等着,等我用完再说。我用完之后资源你们爱怎么抢都行,我占有资源的时候别人都不许抢,申请该资源的线程一律等待。

    信号量(Semaphore)就更灵活一点,我们如果想把我用完的资源给我关系好的人,就申请一个信号量,这个信号量只有我们几个知道,我用完资源就偷偷通知关系好的这几个,这几个哥们再有序申请资源,别的人干瞪眼。

    互斥锁

    1.用不好造成死锁,死锁是A、B两个线程,A需要获得B线程中释放的锁,可以进行。B需要获得A线程中释放的锁,即A不释放B需要的,B就不会释放A需要的,二者僵持,互相锁喉。
    2.互斥锁(Mutex)保证了使用资源线程的唯一性和排他性,但是无法限制资源释放后其他线程申请的顺序问题,所以是无序的。
    3.通常一个线程采取一个互斥锁,当有数据需要写入的时候就上锁,写入完成立即释放锁。就是一个临界区代码保护
    4.互斥锁必须是一个线程中加锁和释放不允许,多线程

    信号量

    1.通常采取二值信号量。其他不常用不记。信号量是由单个线程释放,另一个线程获取,保证线程同步。

    特别注意:互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到

    互斥锁是代码临界区保护
    信号量是通知

    展开全文
  • 本章节讲解 FreeRTOS 任务间的同步和资源共享机制...FreeRTOS 分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数信号量的一种特殊形式,即初始化为仅有一个资源可以使用,只不过 FreeRTOS 对这两种都...

    以下转载自安富莱电子: http://forum.armfly.com/forum.php

    本章节讲解 FreeRTOS 任务间的同步和资源共享机制,二值信号量。 二值信号量是计数信号量的一种特殊形式,即共享资源为 1 的情况。

    FreeRTOS 分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数
    信号量的一种特殊形式,即初始化为仅有一个资源可以使用,只不过 FreeRTOS 对这两种都提供了 API
    函数,而像 RTX,uCOS-II 和 III 是仅提供了一个信号量功能,设置不同的初始值就可以分别实现二值信
    号量和计数信号量。 当然,FreeRTOS 使用计数信号量也能够实现同样的效果。 另外,为什么叫二值信号
    量呢?因为信号量资源被获取了,信号量值就是 0,信号量资源被释放,信号量值就是 1,把这种只有 0
    和 1 两种情况的信号量称之为二值信号量

    函数 xSemaphoreCreateBinary
    函数原型:
    SemaphoreHandle_t xSemaphoreCreateBinary(void)
    函数描述:
    函数 xSemaphoreCreateBinary 用于创建二值信号量。
    返回值,如果创建成功会返回二值信号量的句柄,如果由于 FreeRTOSConfig.h 文件中 heap 大小不
    足,无法为此二值信号量提供所需的空间会返回 NULL。

    FreeRTOS 重要的资源共享机制---互斥信号量(Mutex,即 Mutual Exclusion 的缩写)。
    注意,建议初学者学习完前两个信号量后再学习本章节的互斥信号量

    互斥信号量的主要作用是对资源实现互斥访问,使用二值信号量也可以实现互斥访问的功能,不过互
    斥信号量与二值信号量有区别。 下面我们先举一个通过二值信号量实现资源独享,即互斥访问的例子,让
    大家有一个形象的认识,进而引出要讲解的互斥信号量。
    运行条件:
    让两个任务 Task1 和 Task2 都运行串口打印函数 printf,这里我们就通过二值信号量实现对函数
    printf 的互斥访问。 如果不对函数 printf 进行互斥访问,串口打印容易出现乱码。
    用计数信号量实现二值信号量只需将计数信号量的初始值设置为 1 即可。
    代码实现:

    有了上面二值信号量的认识之后,互斥信号量与二值信号量又有什么区别呢?互斥信号量可以防止优
    先级翻转,而二值信号量不支持,下面我们就讲解一下优先级翻转问题。
     

     

    运行条件:
    创建 3 个任务 Task1,Task2 和 Task3,优先级分别为 3,2,1。 也就是 Task1 的优先级最高。
    任务 Task1 和 Task3 互斥访问串口打印 printf,采用二值信号实现互斥访问。
    起初 Task3 通过二值信号量正在调用 printf,被任务 Task1 抢占,开始执行任务 Task1,也就是上图的起始位置。 
    运行过程描述如下:
    任务 Task1 运行的过程需要调用函数 printf,发现任务 Task3 正在调用,任务 Task1 会被挂起,等
    待 Task3 释放函数 printf。
    在调度器的作用下,任务 Task3 得到运行,Task3 运行的过程中,由于任务 Task2 就绪,抢占了 Task3
    的运行。 优先级翻转问题就出在这里了,从任务执行的现象上看,任务 Task1 需要等待 Task2 执行
    完毕才有机会得到执行,这个与抢占式调度正好反了,正常情况下应该是高优先级任务抢占低优先级
    任务的执行,这里成了高优先级任务 Task1 等待低优先级任务 Task2 完成。 所以这种情况被称之为
    优先级翻转问题
    任务 Task2 执行完毕后,任务 Task3 恢复执行,Task3 释放互斥资源后,任务 Task1 得到互斥资源,
    从而可以继续执行。
    FreeRTOS 互斥信号量的实现
    FreeRTOS 互斥信号量是怎么实现的呢?其实相对于二值信号量,互斥信号量就是解决了一下优先级
    翻转的问题。 下面我们通过如下的框图来说明一下 FreeRTOS 互斥信号量的实现,让大家有一个形象的认识。

    运行条件:
    创建 2 个任务 Task1 和 Task2,优先级分别为 1 和 3,也就是任务 Task2 的优先级最高。
    任务 Task1 和 Task2 互斥访问串口打印 printf。
    使用 FreeRTOS 的互斥信号量实现串口打印 printf 的互斥访问。
    运行过程描述如下:
    低优先级任务 Task1 执行过程中先获得互斥资源 printf 的执行。 此时任务 Task2 抢占了任务 Task1
    的执行,任务 Task1 被挂起。 任务 Task2 得到执行。
    任务 Task2 执行过程中也需要调用互斥资源,但是发现任务 Task1 正在访问,此时任务 Task1 的优
    先级会被提升到与 Task2 同一个优先级,也就是优先级 3,这个就是所谓的优先级继承(Priority
    inheritance),这样就有效地防止了优先级翻转问题。 任务 Task2 被挂起,任务 Task1 有新的优先
    级继续执行。
    任务 Task1 执行完毕并释放互斥资源后,优先级恢复到原来的水平。 由于互斥资源可以使用,任务
    Task2 获得互斥资源后开始执行。
    FreeRTOS 中断方式互斥信号量的实现
    互斥信号量仅支持用在 FreeRTOS 的任务中,中断函数中不可使用。
    互斥信号量 API 函数
    函数 xSemaphoreCreateMutex
    函数原型:
    SemaphoreHandle_t xSemaphoreCreateMutex( void )
    函数描述:
    函数 xSemaphoreCreateMutex 用于创建互斥信号量。
    返回值,如果创建成功会返回互斥信号量的句柄,如果由于 FreeRTOSConfig.h 文件中 heap 大小不
    足,无法为此互斥信号量提供所需的空间会返回 NULL。
    使用这个函数要注意以下问题:
    1. 此函数是基于函数 xQueueCreateMutex 实现的:
    #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
    函数 xQueueCreateMutex 的实现是基于消息队列函数 xQueueGenericCreate 实现的。
    2. 使用此函数要在 FreeRTOSConfig.h 文件中使能宏定义:
    #define configUSE_MUTEXES 1

    互斥信号量, xSemaphoreTake 和 xSemaphoreGive 一定要成对的调用 

    应用举例:

     


     经过测试,互斥信号量是可以被其他任务释放的,但是我们最好不要这么做,因为官方推荐的就是在同一个任务中接收和释放。如果在其他任务释放,不仅仅会让代码整体逻辑变得复杂,还会给使用和维护这套API的人带来困难。遵守规范,总是好的。

    裸机编程的时候,我经常想一个问题,就是怎么做到当一个标志位触发的时候,立即执行某个操作,如同实现标志中断一样,在os编程之后,我们就可以让一个优先级最高任务一直等待某个信号量,如果获得信号量,就执行某个操作,实现类似标志位中断的作用(当然,要想正真做到中断效果,那就需要屏蔽所有可屏蔽中断,而临界区就可以做到)。

    再说一下递归互斥信号量:递归互斥信号量,其实就是互斥信号量里面嵌套互斥信号量

    eg:

    static void vTaskMsgPro(void *pvParameters)
    {
        TickType_t xLastWakeTime;
        const TickType_t xFrequency = 1500;
    
        /* 获取当前的系统时间 */
        xLastWakeTime = xTaskGetTickCount();
        
        while(1)
        {
            /* 递归互斥信号量,其实就是互斥信号量里面嵌套互斥信号量 */
            xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
            {
                /* -------------------------------------- */
                   //假如这里是被保护的资源,第1层被保护的资源,用户可以在这里添加被保护资源
                /* ---------------------------------------------------------------------------- */
                printf("任务vTaskMsgPro在运行,第1层被保护的资源,用户可以在这里添加被保护资源\r\n");
                
                /* 第1层被保护的资源里面嵌套被保护的资源 */
                xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
                {
                    /* ------------------------------------------------------------------------ */
                    //假如这里是被保护的资源,第2层被保护的资源,用户可以在这里添加被保护资源
                    /* ------------------------------------------------------------------------ */
                    printf("任务vTaskMsgPro在运行,第2层被保护的资源,用户可以在这里添加被保护资源\r\n");
                    
                    /* 第2层被保护的资源里面嵌套被保护的资源 */
                    xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
                    {
                        printf("任务vTaskMsgPro在运行,第3层被保护的资源,用户可以在这里添加被保护资源\r\n");
                        bsp_LedToggle(1);
                        bsp_LedToggle(4);
                    }
                    xSemaphoreGiveRecursive(xRecursiveMutex);
                }
                xSemaphoreGiveRecursive(xRecursiveMutex);    
            }
            xSemaphoreGiveRecursive(xRecursiveMutex);
            
            /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
            vTaskDelayUntil(&xLastWakeTime, xFrequency);
        }
    }

     

    可以前面的那个官方文档那样用if判断传递共享量:

    也可以用我们递归互斥信号量里面的portMAX_DELAY指定永久等待,即xSemaphoreTakeRecursive返回的不是pdTRUE时,会一直等待信号量,直到有信号量来才执行后面的语句。

     

    展开全文
  • 信号量互斥量的区别

    千次阅读 2019-11-07 18:53:15
    信号量:那是多线程同步用的,一个线程完成了某一个动作就通过信号告诉别的线程,别的线程再进行某些动作。 互斥量:这是多线程互斥用的,比如说,一个线程占用了某一个资源,那么别的线程就无法访问,知道这个线程...
  • ucos看了也有一周多了,索性源码都能开得懂,并且能去理解。昨天一开始看事件标志组的时候确实不知道怎么回事,后来百度一下,明白了事件标志组的作用以后,再去看书上的讲解和原码就清晰多了,很容易就明白了他的...
  • 互斥信号量

    2018-11-18 09:02:36
    ---关键代码如下--- void CTestSemaphoreDlg::OnBnClickedButtonThread1() {  // TODO: 在此添加控件通知处理程序代码  AfxBeginThread((AFX_THREADPROC)thread1WriteA, this); }     void CTestSemaphoreDlg::...
  • 互斥量和信号量的区别

    万次阅读 多人点赞 2018-04-25 23:36:11
    互斥量和信号量的区别1. 互斥量用于线程的互斥信号量用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但...
  • 信号量---实现同步互斥

    千次阅读 2018-12-14 18:27:12
    了解信号量之前,要先了解临界资源、同步与互斥的概念 1.临界资源:在同一时间只能被一个进程调用的资源,也称互斥资源。 2.同步:保证访问的时序可控性,使调用资源的的顺序合理。 3.互斥:在进程调用临界资源是...
  • 信号量互斥量的区别

    千次阅读 2017-09-19 16:13:28
    信号量互斥量(锁)的区别   一、概念和定义  信号量:多线程同步使用的;一个线程完成某个动作后通过信号告诉别的线程,别的线程才可以执行某些动作;  互斥量:多线程互斥使用的;一个线程占用某个资源,...
  • 11、UCOSIII信号量和互斥信号量

    千次阅读 2018-08-30 15:14:40
    1、 信号量 1.1 信号量简介 ①信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被...
  • UCOS2:对于信号量,互斥信号量,事件标志组的个人理解,看起来挺好的。
  • 【UCOSIII】UCOSIII的互斥信号量

    千次阅读 2018-07-02 21:18:54
    信号量用于控制对共享资源的保护,但是现在基本用来做任务同步用(不太清楚的可以参考链接:【UCOSIII】UCOSIII的信号量)。   优先级反转 优先级反转在可剥夺内核中是非常常见的,在实时系统中不允许出现这种...
  • ucos看了也有一周多了,索性源码都能开得懂,并且能去理解。昨天一开始看事件标志组的时候确实不知道怎么回事,后来百度一下,明白了事件标志组的作用以后,再去看书上的讲解和原码就清晰多了,很容易就明白了他的...
  • **信号量的主要目的有两个:共享资源访问。... 在互斥访问中互斥信号量相当于一个钥匙,当任务想要使用资源的时候就必须先获得这个钥匙,当使用完资源以后就必须归还这个钥匙,这样其他的任务就可以拿着这
  • 二值信号量和互斥信号量的区别

    千次阅读 2014-06-30 16:00:23
    互斥信号量和二进制信号量的区别   互斥型信号量必须是同一个任务申请,同一个任务释放,其他任务释放无效。同一个任务可以递归申请。    二进制信号量,一个任务申请成功后,可以由另一个任务释放。  ...
  • FreeRTOS互斥信号量

    千次阅读 2018-02-28 14:11:56
    API函数 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) #endif QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) ...
  • 互斥信号量可以在资源保护的时候很有帮助。用于控制在两个或多个任务间访问共享资源。任务1里面用互斥,那么任务2只能等任务1访问完再访问同一个变量。 比如全局变量double gADC_value[CH_ADC_NUM] = {0}; //7 adc ...
  • ucosIII 互斥信号量、内嵌信号量

    千次阅读 2015-12-20 20:59:09
    第一部分:互斥信号量,用于解决信号量优先级反转问题 第二部分:内嵌信号量 信号量的优先级反转问题 信号量在一定情况下会造成高优先级的任务反而之后才执行 解决方法:可以将需要等待的任务L优先级上调到和...
  • 为了解决这个问题,引出了互斥信号量的概念。 1:信号量   信号量是一种上锁机制,该任务必须获得相应的钥匙才能进入,直至代码执行结束,释放钥匙,程序才退出。信号量分两种,一种是二进制信号量,一种是计数型
  • 详解UCOS中的互斥信号量

    千次阅读 2014-04-23 09:09:49
    二值信号量主要用于进行共享资源的独占式访问,比如我们用一个变量来标志一个资源是否可用,当这个变量为1的时候表示资源可用,当这个资源为0的时候表示资源不可用,但是二值信号...互斥信号量一般用于降解优先级反转,
  • 互斥信号量和二进制信号量的区别

    千次阅读 2014-05-21 13:16:20
    互斥信号量必须是同一个任务申请,同一个任务释放,其他任务释放无效。同一个任务可以递归申请。    二进制信号量,一个任务申请成功后,可以由另一个任务释放。   二进制信号量实现任务互斥:  打印机...
  • 互斥信号量的初值一般设为1 2、用途 (1)同步信号量的用途:防止被抢占 初始为空 低优先级的任务持有信号量,高优先级的任务需要这个信号量,只有当低优先级的任务give(释放)信号量,高优先级的任务才能take...
  • UCOS-ii中的互斥信号量-优先级反转

    千次阅读 2017-12-26 23:11:17
    二值信号量主要用于进行共享资源的独占式...互斥信号量一般用于降解优先级反转,优先级反转就是高优先级的任务的优先级被拉低了。具体如下: 我们有三个任务Task1,Task2,Task3,三个任务的优先级依次降低。 void
  • 共享资源:变量(静态或全局变量)、数据结构体、RAM表格、I/O设备等。OS在使用一些资源时候
  • 在可剥夺性的内核中,当任务以独占方式... 我们假设有三个任务a,b,c,a优先级高于b,b优先级高于c,a和c都需要访问一个共享资源s,保护该资源的信号量为互斥信号量, 假设当前任务c申请了信号量访问s,还没有释放,此时...
  • 浅析ucosII互斥信号量

    千次阅读 2016-05-05 15:41:10
    所谓优先级翻转问题(priority inversion)即当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,而这个低优先级任务在访问共享资源时可能又被其它一些中等优先级任务抢先,因此造成高...
  • uc/os-ii 互斥信号量及mutex.c源码分析

    千次阅读 2018-04-26 19:56:30
    互斥信号量互斥信号量最主要的功能是对共享资源的互斥访问控制。是一种特殊的二值信号量,它支持所有权、递归访问、任务删除安全等概念,以及一些避免优先级反转、饥饿、死锁等互斥固有问题的解决方法。 ...
  • C++ 多线程中互斥信号量的使用

    千次阅读 2017-07-09 23:10:08
    互斥信号量mutex 互斥量使用示例互斥信号量mutex互斥信号量是一种内核对象,它用来保证一个线程独占一个资源的访问。在使用互斥信号量的时候,有四个主要的函数: (1)CreateMutex,创建互斥信号量。函数原型如下...
  • 在Linux中创建线程和互斥信号量的使用 在Linux中创建线程非常简单,只需要调用pthread_create函数即可。 我们先来看一下该函数的原型: #include<pthread.h> int pthread_create...

空空如也

1 2 3 4 5 ... 20
收藏数 439,076
精华内容 175,630
关键字:

互斥信号量