RT_Thread_信号量

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));。 

参数描述
semrt_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");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值