一、信号量控制块:在include/rtdef.h中

#ifdef RT_USING_SEMAPHORE
/**
* Semaphore structure
*/
struct rt_semaphore
{
struct rt_ipc_object parent; /**< inherit from ipc_object *///派生自IPC对象 rt_uint16_t value; /**< value of semaphore. */ //信号量计数器
};
typedef struct rt_semaphore *rt_sem_t;
#endif

信号量是用来解决线程同步和互斥的通用工具,和互斥量类似,信号量也可用作资源互斥访问,但信号量没有所有者的概念,在应用上比互斥量更广泛。信号量比较简单,不能解决优先级翻转问题,但信号量是一种轻量级的对象,比互斥量小巧、灵活。因此在很多对互斥要求不严格的系统中(或者不会造成优先级翻转的情况下),经常使用信号量来管理互斥资源。value为信号计数器,此信号量多次被释放时将会累加,在被获取时则将减1,当其值为0时,再请求获取的线程将会被挂起到挂起链表中。

二、信号量相关接口:在src/ipc.c中

创建动态信号量:
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);
当调用这个函数时,系统将先分配一个semaphore对象,并初始化这个对象,然后初始化IPC对象以及与semaphore相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。当选择FIFO方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量;当选择PRIO(优先级等待)方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。 删除动态信号量:
rt_err_t rt_sem_delete(rt_sem_t sem);
调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒所有等待在该信号量上的线程(所有等待线程的error返回值是-RT_ERROR,表明为异常唤醒),然后再释放信号量的内存资源。
初始化静态信号量:
rt_err_t rt_sem_init(rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag);
当调用这个函数时,系统将对这个semaphore对象进行初始化,然后初始化IPC对象以及与semaphore相关的部分。在初始化信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的方式。当选择FIFO方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量;当选择PRIO(优先级等待)方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。 脱离静态信号量:
rt_err_t rt_sem_detach(rt_sem_t sem);
使用该函数后,内核先唤醒所有挂在该信号量等待队列上的所有线程,然后将该信号量从内核对象管理器中删除。原来挂起在信号量上的所有等待线程error值将获得-RT_ERROR 的返回值。
获取信号量:
rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time);
线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值都会减1。
在调用这个函数时,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。如果在参数time指定的时间内依然得不到信号量,线程将超时返回,返回值是-RT_ETIMEOUT。
获取信号量函数首先会判断当前是否有信号量(通过value值是否大于0来判断),如果有则立即成功返回,如果没有,则接下来首先判断是否有时间参数,如果等待时间参数为0,则表示需要立即返回,则立即返回错误。如果等待时间参数大于0,则表示需要延时一段时间,在此延时期间,如何信号量到达,或者信号量被非法脱离,或一直没有等到,则通过判断线程的error值来判断当前是否已经成功获得信号值,因为如果成功获得信号量时,即在另一个线程release信号后,因此这一整个过程并没有修改线程的error值,因此,线程的error值一直保持原先的RT_EOK不变。若是线程一直没有等待到信号量的到达,即产生的定时器超时时(在take过程中会将设置一定时器,然后启动它,再挂起当前线程),在线程定时器的回调超时处理函数中,程序会将线程的error值修改为-RT_ETIMEOUT。另,如果之前讲解脱离线程时,如果在某一线程等待信号量期间,这个信号量被意外脱离了时,在脱离信号量的函数中,程序会将线程的error值修改为-RT_ERROR。综上所述,程序可以通过线程的error值来对其是否真正获得信号量进行判定,即如果线程的error值一直保持原样即thread->error==RT_EOK时,则为已获取信号量,否则没有获取,要么超时(-RT_ETIMEOUT),要么非法脱离(-RT_ERROR)了。
无等待获取信号量:
rt_err_t rt_sem_trytake(rt_sem_t sem);
当用户不想在申请的信号量上挂起线程进行等待时,可以使用无等待方式获取信号量,这个函数与rt_sem_take(sem, 0) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回-RT_ETIMEOUT。 释放信号量:
rt_err_t rt_sem_release(rt_sem_t sem);
当线程完成资源的访问后,应尽快释放它持有的信号量,使得其他线程能获得该信号量。当信号量的值等于零时,并且有线程等待这个信号量时,将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量。否则将把信号量的值加1。
控制信号量:
rt_err_t rt_sem_control(rt_sem_t sem, rt_uint8_t cmd, void *arg);
对于cmd,在rtdef.h中只定义了#define RT_IPC_CMD_RESET这一条有效命令,即重新设置信号量值value,同时唤醒所有等待该信号量的线程,参数arg的值为新的信号量值。
只支持重置信号量,此时若其存在挂起线程,则将其全部唤醒再次重新调度。此时在rt_ipc_list_resume_all函数中会将所有挂起的线程的error值设置为-RT_ERROR.

RT-thread内核之信号量的更多相关文章

  1. RT Thread 通过ENV来配置SFUD,操作SPI Flash

    本实验基于正点原子stm32f4探索者板子 请移步我的RT Thread论坛帖子. https://www.rt-thread.org/qa/forum.php?mod=viewthread& ...

  2. STM32 + RT Thread OS 学习笔记[二]

    串口通讯例程 通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作. 1.   目标需求: 开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输 ...

  3. STM32 + RT Thread OS 串口通讯

    1.   创建项目 a)   禁用Finsh和console b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因 ...

  4. RT thread 设备驱动组件之USART设备

    本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...

  5. STM32 + RT Thread OS 学习笔记[三]

    RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...

  6. STM32 + RT Thread OS 学习笔记[四]

    1.  补注 a)      硬件,打通通讯通道 若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到. 从上面的示意图可见,M ...

  7. RT Thread的SPI设备驱动框架的使用以及内部机制分析

    注释:这是19年初的博客,写得很一般,理解不到位也不全面.19年末得空时又重新看了RTThread的SPI和GPIO,这次理解得比较深刻.有时间时再整理上传. -------------------- ...

  8. RT Thread SPI设备 使用

    后记: 之前,我把SPI的片选在Cubemx中配置成了SPI_NSS.现在我给它改为了GPIO_OUTPUT.  同时参考了别人的类似的一个操作无线模块(采用SPI设备驱动)的例子程序(清楚了RTT的 ...

  9. linux内核剖析(十)进程间通信之-信号量semaphore

    信号量 什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明它被占用,测试的线 ...

随机推荐

  1. swoole 相关

    安装虚拟机 VMware Workstation Pro 安装CentOS CentOS-7-x86_64-Minimal-1708.iso 安装FinalShell 教程地址 安装lnmp 教程地址 ...

  2. redis 问题记录

    摘抄来自:https://zhuoroger.github.io/ 1.slowlog和排队延时 slowlog是排查性能问题关键监控指标.它是记录Redis queries运行时间超时特定阀值的系统 ...

  3. Ruby 基础教程1-4

    1.对象 数值对象 字符串对象 数组对象,散列对象 正则表达式对象 时间对象 文件对象 符号对象 2.类 Numeric String Array Hash Regexp File Symbol 3. ...

  4. hdu2899Strange fuction(解方程+二分)

    Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  5. 微信小程序—day04

    元素水平+垂直居中 昨天的用户页的用户头像,是根据已知的像素大小,设置固定的值,达到居中的效果. 今日切换机型进行适配,发现对不同尺寸大小的屏幕不匹配.所以对wxss进行修改,真正达到水平+垂直居中. ...

  6. OSG-基础知识-程序框架

    本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...

  7. Selenium 入门到精通系列:四

    Selenium 入门到精通系列 PS:鼠标右键.鼠标悬停.键盘操作方法 例子 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019 ...

  8. Siki_Unity_1-9_Unity2D游戏开发_Roguelike拾荒者

    Unity 1-9 Unity2D游戏开发 Roguelike拾荒者 任务1:游戏介绍 Food:相当于血量:每走一步下降1,吃东西可以回复(果子10药水20),被怪物攻击会减少中间的障碍物可以打破, ...

  9. leetcode-打家劫舍(动态规划)

    你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警. 给定一个代表每 ...

  10. 记一次Log4j2日志无法输出的 心酸史

    问题描述:部分日志无法输出到日志文件中. 项目中的代码: @Resource private ConfigInfo configInfo; private static final Logger lo ...