首页 > 其他分享 >信号量和互斥信号量

信号量和互斥信号量

时间:2024-02-29 22:55:07浏览次数:21  
标签:处理 中断 信号量 互斥 任务 延迟

注:具体参考文档《FreeRTOS实时内核使用指南-中文.PDF》 3.2 延迟中断处理   二值信号量可以在某个特殊的中断发生时,让任务解除阻塞,相当于让任务与中断 同步。这样就可以让中断事件处理量大的工作在同步任务中完成,中断服务例程(ISR) 中只是快速处理少部份工作。如此,中断处理可以说是被”推迟(deferred)”到一个”处理 (handler)”任务。   如果某个中断处理要求特别紧急,其延迟处理任务的优先级可以设为最高,以保证 延迟处理任务随时都抢占系统中的其它任务。这样,延迟处理任务就成为其对应的 ISR 退出后第一个执行的任务,在时间上紧接着 ISR 执行,相当于所有的处理都在 ISR 中 完成一样。这种方案在图 26 中展现。   延迟处理任务对一个信号量进行带阻塞性质的”take”调用,意思是进入阻塞态以等 待事件发生。当事件发生后,ISR 对同一个信号量进行”give”操作,使得延迟处理任务 解除阻塞,从而事件在延迟处理任务中得到相应的处理。   “获取(Taking,带走,按通常的说法译为获取)”和”给出(Giving)”信号量从概念上讲, 在不同的应用场合有不同的含义。在经典的信号量术语中,获取信号量等同于一个 P() 操作,而给出信号量等同于一个 V()操作。


译者注: P 源自荷兰语 Parsseren,即英语的 Pass;V 源自荷兰语 Verhoog,即英语 的 Increment。P(S)/V(S)操作是信号量的两个原子操作,S 为信号量 Semaphore,相 当于一个标志,可以代表一个资源,一个事件等等,初始值视应用场合而定。P(S)/V(S) 原子操作有如下行为: P(S) : IF (S <= 0) THEN 将本线程加入 S 的等待队列 S = S – 1 V(S) : S = S + 1 IF (S > 0) THEN 唤醒某个等待线程
  在这种中断同步的情形下,信号量可以看作是一个深度为 1 的队列。这个队列由于 最多只能保存一个数据单元,所以其不为空则为满(所谓”二值”)。延迟处理任务调用 xSemaphoreTake()时,等效于带阻塞时间地读取队列,如果队列为空的话任务则进入 阻塞态。当事件发生后,ISR 简单地通过调用 xSemaphoreGiveFromISR()放置一个令 牌(信号量)到队列中,使得队列成为满状态。这也使得延迟处理任务切出阻塞态,并移 除令牌,使得队列再次成为空。当任务完成处理后,再次读取队列,发现队列为空,又 进入阻塞态,等待下一次事件发生。整个流程在图 27 中有所展现。   如图 27 所示,中断给出信号量,甚至是在信号量第一次被获取之前就给出;而任 务在获取信号量之后再也不给回来。这就是为什么说这种情况与读写队列相似。这也经 常会给大家造成迷惑,因为这种情形和其它信号量的使用场合大不相同。在其它场合下, 任务获得(Take)了信号量之后,必须得给(Give)回来——如同第四章描述一样。

 

  3.3 计数信号量   例 12 演示了一个二值信号量被用于让任务和中断进行同步。整个执行流程可以描 述为:   1. 中断产生。   2. 中断服务例程启动,给出信号量以使延迟处理任务解除阻塞。   3. 当中断服务例程退出时,延迟处理任务得到执行。延迟处理任务做的第一件事便是    获取信号量。   4. 延迟处理任务完成中断事件处理后,试图再次获取信号量——如果此时信号量无效,      任务将切入阻塞待等待事件发生。     在中断以相对较慢的频率发生的情况下,上面描述的流程是足够而完美的。如果在 延迟处理任务完成上一个中断事件的处理之前,新的中断事件又发生了,等效于将新的 事件锁存在二值信号量中,使得延迟处理任务在处理完上一个事件之后,立即就可以处 理新的事件。也就是说,延迟处理任务在两次事件处理之间,不会有进入阻塞态的机会, 因为信号量中锁存有一个事件,所以当 xSempaphoreTake()调用时,信号量立即有效。 这种情形将在图 30 中进行展现。   在图 30 中可以看到,一个二值信号量最多只可以锁存一个中断事件。在锁存的事 件还未被处理之前,如果还有中断事件发生,那么后续发生的中断事件将会丢失。如果 用计数信号量代替二值信号量,那么,这种丢中断的情形将可以避免。 就如同我们可以把二值信号量看作是只有一个数据单元的队列一样,计数信号量可 以看作是深度大于 1 的队列。任务其实对队列中存储的具体数据并不感兴趣——其只关 心队列是空还是非空。   计数信号量每次被给出(Given),其队列中的另一个空间将会被使用。队列中的有 效数据单元个数就是信号量的”计数(Count)”值。

 

 

 

计数信号量有以下两种典型用法: 1.事件计数 在这种用法中,每次事件发生时,中断服务例程都会“给出(Give)”信号量——信号 量在每次被给出时其计数值加 1。延迟处理任务每处理一个任务都会”获取(Take)”一次 信号量——信号量在每次被获取时其计数值减 1。信号量的计数值其实就是已发生事件 的数目与已处理事件的数目之间的差值。这种机制可以参考图 31。 用于事件计数的计数信号量,在被创建时其计数值被初始化为 0。 2.资源管理 在这种用法中,信号量的计数值用于表示可用资源的数目。一个任务要获取资源的 控制权,其必须先获得信号量——使信号量的计数值减 1。当计数值减至 0,则表示没 有可用资源。当任务利用资源完成工作后,将给出(归还)信号量——使信号量的计数值 加 1。 用于资源管理的信号量,在创建时其计数值被初始化为可用资源总数。第四章涵盖 了使用信号量来管理资源。  

4.3 互斥量(及二值信号量)

  互斥量是一种特殊的二值信号量,用于控制在两个或多个任务间访问共享资源。单 词MUTEX(互斥量)源于”MUTual EXclusion”。     在用于互斥的场合,互斥量从概念上可看作是与共享资源关联的令牌。一个任务想 要合法地访问资源,其必须先成功地得到(Take)该资源对应的令牌(成为令牌持有者)。 当令牌持有者完成资源使用,其必须马上归还(Give)令牌。只有归还了令牌,其它任务 才可能成功持有,也才可能安全地访问该共享资源。一个任务除非持有了令牌,否则不 允许访问共享资源。这种机制在图 36 中展示。     虽然互斥量与二值信号量之间具有很多相同的特性,但图 36 展示的情形(互斥量用 于互斥功能)完全不同于图 30 展示的情形(二值信号量用于同步)。两者间最大的区别在 于信号量在被获得之后所发生的事情:  
  • 用于互斥的信号量必须归还。
  • 用于同步的信号量通常是完成同步之后便丢弃,不再归还。

 

标签:处理,中断,信号量,互斥,任务,延迟
From: https://www.cnblogs.com/wang-1962918321/p/18045772

相关文章

  • GIL锁、互斥锁
    一、GIL锁1、全局解释器锁(GlobalInterpreterLock,简称GIL)GIL是一种用于保护Python解释器在多线程环境下的数据完整性的机制。GIL只存在是CPython解释器中,即官方的Python解释器实现GIL是一个互斥锁,你可以使用多线程来并发处理任务,但在同一时刻只能有一个线程......
  • Qt 设置button互斥,一组button只能选中一个
    一、同一容器内互斥效果1.先在界面是拖入一个控件容器,这里以QGroupBox为例2.再放进来几个按钮控件3.设置按钮属性,第一个红框勾选是设置按钮可选,第二个勾选就是设置自动互斥,当同一容器内的按钮勾选了这个选项就会自动互斥二、不同容器内互斥效果1.还是先设置所要互斥的......
  • 锁 条件变量 信号量
    锁-条件变量-信号量用一个例子引入,用于输出嵌套深度不超过n的括号序列。voidTproduce(){while(1){mutex_lock(&lk);if(!CAN_PRODUCE){cond_wait(&cv,&lk);}printf("(");count++;cond_signal(&cv);mutex_unlock(&lk);}}......
  • Python并发编程之进程池,线程池与信号量
    【一】进程池和线程池【0】池池的概念:资源管理:池用于管理和维护一组资源(如进程或线程),而不是每次需要时都创建和销毁这些资源。这有助于减少创建和销毁的开销。并发处理:池允许并发地执行多个任务,每个任务由池中的一个资源处理。这提高了程序的并发性能。任务队列:池通......
  • 【6.2】线程的互斥锁
    【一】问题所有子线程都会进行阻塞操作,导致最后的改变只是改了一次fromthreadingimportThreadimporttimemoney=100deftask():globalmoney#模拟获取到车票信息temp=money#模拟网络延迟time.sleep(2)#模拟购票money=......
  • 【9.0】信号量和事件
    【一】信号量(了解)信号量Semahpore(同线程一样)【1】引入互斥锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去如果指定信号量为3,那么来一个人获得一把锁,计数加1,当......
  • 进程锁(互斥锁)
    进程锁(互斥锁)【一】什么是进程同步(互斥锁)互斥锁(Mutex)是一种用于多线程编程中控制对共享资源访问的机制。其作用是保证在同一时刻只有一个线程在访问共享资源,从而避免多个线程同时读写数据造成的问题。互斥锁的基本原理是在对共享资源进行访问前加锁,使得其他线程无法访问该......
  • 基于信号量的环形队列的生成消费模型(万字长文详解)
    linux线程之信号量POSIX信号量阻塞队列的缺陷==这是一个我们自己的实现阻塞队列!==classBlockQueue{public:BlockQueue(constint&maxcap=gmaxcap):maxcap_(maxcap){pthread_mutex_init(&mutex_,nullptr);......
  • 线程同步之信号量
    目录Semaphore信号量Semaphore与condition_variable的区别Semaphore信号量在C++中,可以使用std::Semaphore类来实现信号量。信号量可以用于控制对资源的访问,例如限制同时执行任务的线程数量。在C++11中,std::Semaphore类提供了以下常用函数:Semaphore():构造函数,创建一个信......
  • linux之线程互斥(万字长文详解)
    linux之线程互斥多线程在访问共享资源时的问题假如我们设置一个全局变量!inttickets=1000;//充当有1000张票void*getTicket(void*args){std::stringusername=static_cast<constchar*>(args);while(true){if(tickets>0){......