1、信号量
1.1、创建和删除信号量
静态信号量
rt_err_t rt_sem_init(rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag)
只看函数声明,信号量的初始值value是32位,但实际是16位的:
参数 | 描述 |
---|---|
sem | 信号量对象的句柄 |
name | 信号量名称 |
value | 信号量初始值 |
flag | 信号量标志,它可以取如下数值: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO |
返回 | —— |
RT_EOK | 初始化成功 |
rt_err_t rt_sem_detach(rt_sem_t sem);
内核先唤醒所有挂在该信号量等待队列上的线程,然后将该信号量从内核对象管理器中脱离。
参数 | 描述 |
---|---|
sem | 信号量对象的句柄 |
返回 | —— |
RT_EOK | 脱离成功 |
动态信号量
rt_sem_t rt_sem_create(const char *name,
rt_uint32_t value,
rt_uint8_t flag);
参数 | 描述 |
---|---|
name | 信号量名称 |
value | 信号量初始值 |
flag | 信号量标志,它可以取如下数值: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO; 建议采用 RT_IPC_FLAG_PRIO,即确保线程的实时性。 |
返回 | —— |
RT_NULL | 创建失败 |
信号量的控制块指针 | 创建成功 |
rt_err_t rt_sem_delete(rt_sem_t sem);
唤醒等待在该信号量上的线程,_ipc_list_resume_all(&(sem->parent.suspend_thread));。
参数 | 描述 |
---|---|
sem | rt_sem_create() 创建的信号量对象 |
返回 | —— |
RT_EOK | 删除成功 |
1.2、获取信号量
信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1;
信号量的值等于零,说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择直接返回、或挂起等待一段时间、或永久等待;
rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time);
参数 | 描述 |
---|---|
sem | 信号量对象的句柄 |
time | 指定的等待时间,单位是操作系统时钟节拍(OS Tick) |
返回 | —— |
RT_EOK | 成功获得信号量 |
-RT_ETIMEOUT | 超时依然未获得信号量 |
-RT_ERROR | 其他错误 |
rt_sem_trytake是不等待获取信号量,与 rt_sem_take(sem, RT_WAITING_NO)
的作用相同
rt_err_t rt_sem_trytake(rt_sem_t sem);
参数 | 描述 |
---|---|
sem | 信号量对象的句柄 |
返回 | —— |
RT_EOK | 成功获得信号量 |
-RT_ETIMEOUT | 获取失败 |
1.3、释放信号量
rt_err_t rt_sem_release(rt_sem_t sem);
参数 | 描述 |
---|---|
sem | 信号量对象的句柄 |
返回 | —— |
RT_EOK | 成功释放信号量 |
2、生产者和消费者
2.1、描述
有一块共享的内存空间,生产者负责写入数据,消费者负责读出数据。
对于生产者线程:有空位的时候,才能写入数据,写完数据后标记数据的数量加1;
对于消费者线程:有数据的时候,才能读出数据,读出数据后标记数据的空位加1;
2.2、代码
/* 生产者线程入口 */
void producer_thread_entry(void *parameter)
{
int cnt = 0;
while (cnt < 10)
{
/* 获取一个空位 */
rt_sem_take(&sem_empty, RT_WAITING_FOREVER);
/* 修改array内容,上锁 */
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
array[set % MAXSEM] = cnt + 1;
rt_kprintf("the producer generates a number: %d\n", array[set % MAXSEM]);
set++;
rt_sem_release(&sem_lock);
/* 发布一个满位 */
rt_sem_release(&sem_full);
cnt++;
rt_thread_mdelay(20);
}
rt_kprintf("the producer exit!\n");
}
/* 消费者线程入口 */
void consumer_thread_entry(void *parameter)
{
rt_uint32_t sum = 0;
while (1)
{
/* 获取一个满位 */
rt_sem_take(&sem_full, RT_WAITING_FOREVER);
/* 临界区,上锁进行操作 */
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
sum += array[get % MAXSEM];
rt_kprintf("the consumer[%d] get a number: %d\n", (get % MAXSEM), array[get % MAXSEM]);
get++;
rt_sem_release(&sem_lock);
/* 释放一个空位 */
rt_sem_release(&sem_empty);
/* 生产者生产到10个数目,停止,消费者线程相应停止 */
if (get == 10) break;
rt_thread_mdelay(50);
}
rt_kprintf("the consumer sum is: %d\n", sum);
rt_kprintf("the consumer exit!\n");
}