RT-Thread学习笔记——信号量

前言

本文讲RT-Thread的线程间同步之信号量,包括为什么要进行线程间同步、信号量创建与删除、信号量获取与释放以及基于STM32的二值信号量示例和计算型信号量示例,采用RTT&正点原子联合出品潘多拉开发板进行实验。

一、线程间同步

1、什么是线程间同步?

同步是指按预定的先后次序进行运行,线程同步是指多个线程通过特定的机制来控制线程之间的执行顺序,也可以说是在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间将是无序的。 

2、为什么要进行线程间同步?

例如一项工作中的两个线程:一个线程从传感器中接收数据并且将数据写到共享内存中,同时另一个线程周期性的从共享内存中读取数据并发送去显示,下图描述了两个线程间的数据传递: 

线程间数据传递示意图
线程间数据传递示意图(来源RT-Thread编程指南)

如果对共享内存的访问不是排他性的,那么各个线程间可能同时访问它,这将引起数据一致性的问题。例如,在显示线程试图显示数据之前,接收线程还未完成数据的写入,那么显示将包含不同时间采样的数据,造成显示数据的错乱。将传感器数据写入到共享内存块的接收线程 #1 和将传感器数据从共享内存块中读出的线程 #2 都会访问同一块内存。为了防止出现数据的差错,两个线程访问的动作必须是互斥进行的,应该是在一个线程对共享内存块操作完成后,才允许另一个线程去操作,这样,接收线程 #1 与显示线程 #2 才能正常配合,使此项工作正确地执行。 

 

二、信号量

信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数。其值的含义分两种情况:(1) 0,表示没有积累下来的 release 释放信号量操作,且有可能有在此信号量上阻塞的线程。(2)正值,表示有一个或多个 release 释放信号量操作。

1、 互斥为目的的信号量:用作互斥时,信号量创建后可用信号量个数应该是满的,线程在需要使用临界资源时,先获取信号量,使其变空,这样其他线程需要使用临界资源时就会因为无法获取信号量而进入阻塞,从而保证了临界资源的安全。

2、同步为目的的信号量:用作同步时,信号量在创建后被置为空,线程 1 取信号量而阻塞,线程 2 在某种条件发生后,释放信号量,于是线程 1 得以进入就绪态,如果线程 1 的优先级是最高的,那么就会立即切换线程,从而达到了两个线程间的同步。同样的,在中断服务函数中释放信号量,也能达到线程与中断间的同步。

3、创建动态信号量函数:当创建一个信号量时,内核首先创建一个信号量控制块,然后对该控制块进行基本的初始化工作。信号量标志参数flag决定了当信号量不可用时,多个线程等待的排队方式。当选择 RT_IPC_FLAG_FIFO(先进先出)方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量;当选择RT_IPC_FLAG_PRIO(优先级等待)方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。

rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);

 (1)入口参数:

  name:信号量名称。
  value:信号量初始值。
  flag:信号量标志,它可以取如下数值:RT_IPC_FLAG_FIFO 或RT_IPC_FLAG_PRIO。

(2)返回值

  RT_NULL:创建失败。
  信号量的控制块指针:创建成功。

4、删除动态信号量函数:系统不再使用动态信号量时,可通过删除动态信号量以释放系统资源,如果系统删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是- RT_ERROR),然后再释放信号量的内存资源。

rt_err_t rt_sem_delete(rt_sem_t sem);

(1)入口参数:

  sem:创建的信号量对象。

(2)返回值:

  RT_EOK:删除成功。

5、创建静态信号量函数:创建静态信号量也就是《RT-Thread编程指南》所讲的初始化信号量。对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。

rt_err_t rt_sem_init(rt_sem_t    sem,
                     const char *name,
                     rt_uint32_t value,
                     rt_uint8_t  flag);

(1)入口参数:

 sem:信号量对象的句柄。
 name:信号量名称。
 value

  • 18
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值