一.信号量
信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。
每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例。
二.信号量的使用和管理
对一个信号量的操作包含:创建 / 初始化信号量、获取信号量、释放信号量、删除 / 脱离信号量。

三. 创建和删除信号量(动态创建)

系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。
调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是-RT_ERROR),然后再释放信号量的内存资源。
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
rt_sem_t sem1;
int main(void)
{
sem1=rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
if(sem1==RT_NULL)
{
LOG_E("rt_sem_create failed...\n");
return -RT_ENOMEM;
}
LOG_E("rt_sem_create successed...\n");
}

四. 初始化和脱离信号量
/**
* This function will initialize a semaphore and put it under control of
* resource management.
*
* @param sem the semaphore object
* @param name the name of semaphore
* @param value the initial value of semaphore
* @param flag the flag of semaphore
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_sem_init(rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag)
/**
* This function will detach a semaphore from resource management
*
* @param sem the semaphore object
*
* @return the operation status, RT_EOK on successful
*
* @see rt_sem_delete
*/
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
struct rt_semaphore sem2;
int main(void)
{
rt_sem_init(&sem2, "sem2", 0, RT_IPC_FLAG_FIFO);
if(sem1==RT_NULL)
{
LOG_E("rt_sem_init failed...\n");
return -RT_ENOMEM;
}
LOG_E("rt_sem_init successed...\n");
}

五.获取信号量
线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。如果在参数time指定的时间内依然得不到信号量,线程将超时返回,返回值是 – RT_ETIMEOUT。

六.释放信号量
释放信号量可以唤醒挂起在该信号量上的线程。
/**
* This function will release a semaphore, if there are threads suspended on
* semaphore, it will be waked up.
*
* @param sem the semaphore object
*
* @return the error code
*/
rt_err_t rt_sem_release(rt_sem_t sem)
七.信号量实例

#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
rt_sem_t sem1;
struct rt_semaphore sem2;
rt_thread_t th1,th2;
int flags=0;
//线程1的入口函数
void th1_entry(void *parameter)
{
while(1)
{
rt_thread_mdelay(1000);
rt_sem_take(sem1, RT_WAITING_FOREVER);
flags++;
if(flags==100)
flags=0;
rt_kprintf("th1_entry [%d]\n",flags);
rt_sem_release(&sem2);
}
}
//线程2的入口函数
void th2_entry(void *parameter)
{
while(1)
{
rt_thread_mdelay(2000);
rt_sem_take(&sem2, RT_WAITING_FOREVER);
if(flags>0)
flags--;
rt_kprintf("th2_entry [%d]\n",flags);
rt_sem_release(sem1);
}
}
int main(void)
{
//动态信号量的创建sem1
sem1=rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
if(sem1==RT_NULL)
{
LOG_E("rt_sem_create failed...\n");
return -RT_ENOMEM;
}
LOG_D("rt_sem_create successed...\n");
//静态信号量的创建sem2
int ret=0;
ret=rt_sem_init(&sem2, "sem2", 0, RT_IPC_FLAG_FIFO);
if(ret<0)
{
LOG_E("rt_sem_init failed...\n");
return -RT_ENOMEM;
}
LOG_D("rt_sem_init successed...\n");
//线程1的创建
th1=rt_thread_create("th1", th1_entry, NULL, 512, 20, 5);
if(th1==RT_NULL)
{
LOG_E("th1 rt_thread_create failed...\n");
return -RT_ENOMEM;
}
LOG_D("th1 rt_thread_create successed...\n");
//线程2的创建
th2=rt_thread_create("th2", th2_entry, NULL, 512, 20, 5);
if(th1==RT_NULL)
{
LOG_E("th2 rt_thread_create failed...\n");
return -RT_ENOMEM;
}
LOG_D("th2 rt_thread_create successed...\n");
rt_thread_startup(th1);
rt_thread_startup(th2);
return 0;
}
