多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生。
RTT使用信号量、互斥量、事件集来解决这种问题。
同步(按顺序)、互斥(排它)。
信号量
信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。
每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为5,则表示共有5个信号量实例可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例。
struct rt_semaphore
{
struct rt_ipc_object parent; /**< inherit from ipc_object */
rt_uint16_t value; /**< value of semaphore. */
rt_uint16_t reserved; /**< reserved field */
};
动态创建:rt_sem_create();
系统不再使用信号量时,可以通过删除信号量以释放系统资源,适用于动态创建的信号量。调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是-RT_ERROR),然后再释放信号量的内存资源。
静态创建的时候,定义一个结构体变量,而不是结构体指针,系统会为它分配空间。
信号量的使用
获取信号量:
线程通过获取信号量来获得信号量资源实例,当信号量值大于0时,线程将获得信号量,并且相应的信号量值会减1,如果信号量的值等于0,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其它线程或中断释放该信号量。如果在参数time指定的时间内依然得不到信号量,线程将超时返回,返回值是-RT ETIMEOUT。
rt_sem_take();
rt_sem_release();
互斥量
互斥量体现的是排他性,类似于特殊的信号量——二值信号量。
区别:信号量可以由不同的线程释放,互斥量只能由同一线程释放。
事件集
事件集是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。
一个线程和多个事件的关系可设置为:
其中任意一个事件唤醒线程,或几个事件都到达后唤醒线程,多个事件集合可以用一个32bit无符号整形变量来表示,变量的每一位代表一个时间,线程通过“逻辑与”或“逻辑或”将一个或多个事件关联起来,形成事件组合。
- 事件只与线程相关,事件间相互独立。
- 事件仅用于同步,不提供数据传输功能。
- 事件无排队性,即多次向线程发送同一事件(如果线程还未来得及读走),其效果等同于只发送一次。