信号量
注意信号量和信号没有关系,信号是用来通知的,信号量则表示资源的数量,支持的动作:"give"给出资源,计数值加 1;"take"获得资源,计数值减 1。
在rtt中,使用使用结构体 struct rt_semaphore 来管理信号量,成员 rt_uint16_t value 表示信号量的值,最大为 65535。:
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_t 来表示一个信号量
创建/初始化:使用信号量之前,要先创建,得到一个句柄;使用信号量时,要使用句柄来表明使用哪个信号量。信号量的创建有两种方法:动态分配内存rt_sem_create()、静态分配内存rt_sem_init(),
rt_sem_t rt_sem_create(const char *name,rt_uint32_t value,rt_uint8_t flag)
rt_err_t rt_sem_init(rt_sem_t sem,const char *name,rt_uint32_t value,rt_uint8_t flag)
//其中flag的用法和消息队列中一样,可取RT_IPC_FLAG_FIFO 和 RT_IPC_FLAG_PRIO
删除/脱离:不再使用一个信号量时,删除它:rt_sem_delete();脱离它:rt_sem_detach()
删除消息队列的函数为 rt_sem_delete(),它会释放内存。删除信号量时,如果有线程正在等待该信号量,则内核会先唤醒这些线程(线程返回值是 - RT_ERROR),然后再释放信号量使用的内存,最后删除信号量对象。原型如下:
rt_err_t rt_sem_delete(rt_sem_t sem);
脱离信号量,就是将信号量对象被从内核对象管理器中脱离。脱离信号量时,如果有线程在等待该信号量,则内核会先唤醒这些线程。原型如下:
rt_err_t rt_sem_detach(rt_sem_t sem)
获取/释放:RT-Thread 有两个获取信号量的函数,一个释放信号量函数:rt_sem_take() 获取信号量,rt_sem_trytake() 无等待、尝试获取信号量,rt_sem_release() 释放信号量。
- 使用 rt_sem_take()获取信号量时,信号量的值大于 0,线程将获得信号量,信号量值减 1;当信号量的值等于 0 时,线程会根据 timeout 参数等待,超时后才返回错误( -RT_ETIMEOUT)
- 使用 rt_sem_trytake()获取信号量时,信号量的值大于 0,线程将获得信号量,信号量值减 1;当信号量的值等于 0 时,线程会直接返回,和 rt_sem_take(sem, RT_WAITING_NO)作用相同,即不会等待。
- 使用 rt_sem_release()将释放信号量:如果有线程在等待这个信号量,此函数不会累加信号量的值,而是直接唤醒等待的线程(唤醒顺序和flag有关),如果没有线程在等待这个信号量,此函数会累加信号量的值
获取信号量的函数原型如下:
rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time);
time:超时时间,单位为系统时钟节拍(OS Tick)
无等待获取信号量的函数原型如下:
rt_err_t rt_sem_trytake(rt_sem_t sem);
释放信号量的函数原型如下:
rt_err_t rt_sem_release(rt_sem_t sem);