RT_Thread内核机制学习(六)信号量

news/2025/3/19 21:28:55/

要传输较大数据时,使用队列。
传输较小数值时,使用邮箱。

队列、邮箱用来传递数据。
如果只是用来传递资源的个数,可以使用信号量。

在这里插入图片描述
A车与B车只需要传递信号量(代表资源)。

信号量

获取信号量

  1. 如果value>0,value–,return OK;如果value0,timeout0,return -ETIMEOUT;如果value==0,timeout>0,从就绪链表移除(挂起),把自己记录在信号量的等待链表。
  2. 被唤醒:如果thread->err!=0,return thread->err;return EOK;

释放信号量

  1. value++;如果有等待信号量线程,唤醒线程。

创建信号量

/*** This function will create a semaphore from system resource** @param name the name of semaphore* @param value the initial value of semaphore* @param flag the flag of semaphore** @return the created semaphore, RT_NULL on error happen** @see rt_sem_init*/
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)

信号量结构体

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 */
};struct rt_ipc_object
{struct rt_object parent;                            /**< inherit from rt_object */rt_list_t        suspend_thread;                    /**< threads pended on this resource */
};

获取信号量

rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
{register rt_base_t temp;struct rt_thread *thread;/* parameter check */RT_ASSERT(sem != RT_NULL);RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(sem->parent.parent)));/* disable interrupt */temp = rt_hw_interrupt_disable(); //关中断RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s take sem:%s, which value is: %d\n",rt_thread_self()->name,((struct rt_object *)sem)->name,sem->value));if (sem->value > 0) //如果有资源{/* semaphore is available */sem->value --;/* enable interrupt */rt_hw_interrupt_enable(temp);}else{/* no waiting, return with timeout */if (time == 0){rt_hw_interrupt_enable(temp);return -RT_ETIMEOUT;}else{/* current context checking */RT_DEBUG_IN_THREAD_CONTEXT;/* semaphore is unavailable, push to suspend list *//* get current thread */thread = rt_thread_self();/* reset thread error number */thread->error = RT_EOK;RT_DEBUG_LOG(RT_DEBUG_IPC, ("sem take: suspend thread - %s\n",thread->name));/* suspend thread */rt_ipc_list_suspend(&(sem->parent.suspend_thread),thread,sem->parent.parent.flag);/* has waiting time, start thread timer */if (time > 0){RT_DEBUG_LOG(RT_DEBUG_IPC, ("set thread:%s to timer list\n",thread->name));/* reset the timeout of thread timer and start it */rt_timer_control(&(thread->thread_timer),RT_TIMER_CTRL_SET_TIME,&time);rt_timer_start(&(thread->thread_timer));}/* enable interrupt */rt_hw_interrupt_enable(temp);/* do schedule */rt_schedule();if (thread->error != RT_EOK){return thread->error;}}}RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(sem->parent.parent)));return RT_EOK; //获取到了资源成功返回
}
RTM_EXPORT(rt_sem_take);

释放信号量

rt_err_t rt_sem_release(rt_sem_t sem)
{register rt_base_t temp;register rt_bool_t need_schedule;/* parameter check */RT_ASSERT(sem != RT_NULL);RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(sem->parent.parent)));need_schedule = RT_FALSE;/* disable interrupt */temp = rt_hw_interrupt_disable();RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s releases sem:%s, which value is: %d\n",rt_thread_self()->name,((struct rt_object *)sem)->name,sem->value));if (!rt_list_isempty(&sem->parent.suspend_thread)) //是否有等待线程{/* resume the suspended thread */rt_ipc_list_resume(&(sem->parent.suspend_thread));//唤醒++,接收--,所以没有对sem->value做任何操作。need_schedule = RT_TRUE;}elsesem->value ++; /* increase value *//* enable interrupt */rt_hw_interrupt_enable(temp);/* resume a thread, re-schedule */if (need_schedule == RT_TRUE)rt_schedule();return RT_EOK;
}
RTM_EXPORT(rt_sem_release);

在这里插入图片描述


http://www.ppmy.cn/news/1070376.html

相关文章

Pyecharts教程(九):使用Pyecharts绘制K线图的基本示例

Pyecharts教程(九):使用Pyecharts绘制K线图的基本示例 作者:安静到无声 个人主页 目录 Pyecharts教程(九):使用Pyecharts绘制K线图的基本示例完整代码推荐专栏引言: K线图是用于展示股票、期货等金融市场价格变动的一种图表形式。在Python中,可以使用Pyecharts库来绘制K线…

如何在YouTube平台成功开展联盟营销?详细攻略

在当今数字化时代&#xff0c;联盟营销已成为企业实现品牌曝光、拓展市场的重要策略之一。而YouTube作为全球最大的视频分享平台&#xff0c;拥有庞大的用户群体和广告资源&#xff0c;成为许多企业开展联盟营销的理想平台。本文将为您介绍如何在YouTube平台上开展联盟营销并获…

VMware虚拟机---Ubuntu无法连接网络该怎么解决?

在学习使用Linux系统时&#xff0c;由于多数同学们的PC上多是Windows系统&#xff0c;故会选择使用VMware创建一个虚拟机来安装Linux系统进行学习。 安装完成之后&#xff0c;在使用时总是会遇到各种各样的问题。本片随笔就主要针对可能出现的网络问题进行一个总结&#xff0c;…

配置uniapp调试环境

目录 uni-app介绍 uni-app开发工具HBuilderX 创建项目前提条件 uni-app项目结构 配置mumu模拟器 uni-app生命周期 1.应用生命周期 小程序规范 2.页面生命周期-小程序规范 3.组件生命周期 vue规范 uni-app登录按钮方法 uni-app发布安卓app uni-app介绍 uni-app 是一个…

23款奔驰S400商务型升级裸眼3D仪表盘,体验高配乐趣

3D驾驶员显示屏能帮助您密切留意该显示屏中的重要信息。驾驶辅助系统的警告图标和功能图标都有醒目的3D效果&#xff0c;能够立即引起驾驶员的注意。不仅如此&#xff0c;显示屏还能以出色的 3D 影像来显示车辆前方的汽车、卡车、客车和摩托车等车辆。

Kratos源码-日志-目录

文章目录 前言一、Java中的日志门面二、源码分析总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、Java中的日志门面 Kratos源码-Java中的日志框架 二、源码分析 Kratos源码-Logging 总结

Arduino RGBLED灯 模块学习与使用

Arduino RGBLED灯模块学习与使用 硬件原理制作衍生连接线Mixly程序Arduino程序演示视频 人生如逆旅&#xff0c;我亦是行人。 —— 苏轼江客:时荒 硬件原理 RGBLED灯三个引脚分别控制三个LED灯的亮度&#xff0c;RGB分别是red&#xff0c;green&#xff0c;blue的英文缩写&…

开源项目的文档:为什么它如此重要?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…