在ThreadX中如何使用信号量详解

ThreadX学习(1)——概述 ThreadX学习(1)——概述学习参考:组件 学习参考: 《Real-Time Embedded Multithreading: Using ThreadX and ARM》 安富莱_STM32-V7开发板ThreadX内核教程(V0.7) 组件 某些组件是公共资源,这意味着它可以从任何线程访问。访问一个组件与拥有它是不同的。例如,互斥锁可以被任何线程访问,但一次只能被一个线程拥有。 ... 阅读详情

什么是信号量?

信号量是一种常用的线程间同步和资源管理的机制,它可以用来表示信号对象或资源的数量。在ThreadX中,信号量是一个32位的计数值,它可以通过函数tx_semaphore_create创建,并指定一个初始值。信号量的值可以通过函数tx_semaphore_get和tx_semaphore_put来增加或减少,从而实现线程间的协调和通信。

在这里插入图片描述

信号量的概念和作用

信号量的概念最早由Edgser Dijkstra在20世纪60年代中期提出,用来解决多个线程访问共享资源的问题。信号量可以看作是一个表示资源数量的标志,当一个线程要访问共享资源时,它需要先检查信号量的值,如果信号量的值大于零,说明有可用的资源,那么线程就可以获取信号量,并将信号量的值减一,然后访问共享资源;如果信号量的值等于零,说明没有可用的资源,那么线程就需要等待,直到有其他线程释放信号量,并将信号量的值加一,然后再尝试获取信号量。

信号量的作用主要有两方面:

  • 线程间的同步:当信号量的值表示某个事件的发生次数时,信号量可以用来实现线程间的同步。例如,一个线程可以通过函数tx_semaphore_put来发送信号量,表示某个事件已经发生,另一个线程可以通过函数tx_semaphore_get来等待信号量,表示等待某个事件的发生。这样,两个线程就可以通过信号量来协调自己的行为,实现同步的目的。
  • 资源的管理:当信号量的值表示某种资源的数量时,信号量可以用来实现资源的管理。例如,一个系统有多个设备,每个设备都需要一个驱动程序来控制,那么可以用一个信号量来表示可用的驱动程序的数量,每个线程在使用设备之前,需要先通过函数tx_semaphore_get来获取信号量,表示占用一个驱动程序,使用完设备之后,需要通过函数tx_semaphore_put来释放信号量,表示释放一个驱动程序。这样,信号量就可以用来避免多个线程同时访问同一个设备,造成冲突或错误。

信号量的创建和删除

在ThreadX中,信号量是一种内核对象,它需要通过函数tx_semaphore_create来创建,并指定一个名称和一个初始值。例如,下面的代码创建了一个名为semaphore的信号量,初始值为10:

TX_SEMAPHORE semaphore; //定义一个信号量变量
tx_semaphore_create(&semaphore, "semaphore", 10); //创建信号量,初始值为10

信号量创建成功后,就可以通过函数tx_semaphore_get和tx_semaphore_put来操作信号量的值。当信号量不再需要时,可以通过函数tx_semaphore_delete来删除信号量,释放内存空间。例如,下面的代码删除了之前创建的信号量:

tx_semaphore_delete(&semaphore); //删除信号量

信号量的获取和释放

在ThreadX中,信号量的获取和释放是通过函数tx_semaphore_get和tx_semaphore_put来实现的。函数tx_semaphore_get用来获取信号量,如果信号量的值大于零,那么函数会将信号量的值减一,并立即返回;如果信号量的值等于零,那么函数会将调用线程挂起,直到信号量的值变为正数,或者超时。函数tx_semaphore_put用来释放信号量,函数会将信号量的值加一,并唤醒等待信号量的线程。例如,下面的代码演示了两个线程如何通过信号量来实现同步:

//定义两个线程的入口函数
void thread1_entry(ULONG entry_input)
{
    while(1)
    {
        //做一些工作
        //...
        //发送信号量,表示事件已经发生
        tx_semaphore_put(&semaphore);
        //延时一段时间
        tx_thread_sleep(100);
    }
}

void thread2_entry(ULONG entry_input)
{
    while(1)
    {
        //等待信号量,表示等待事件的发生
        tx_semaphore_get(&semaphore, TX_WAIT_FOREVER);
        //做一些工作
        //...
    }
}

//定义两个线程的控制块和栈空间
TX_THREAD thread1;
TX_THREAD thread2;
UCHAR thread1_stack[1024];
UCHAR thread2_stack[1024];

//定义一个信号量
TX_SEMAPHORE semaphore;

//在主函数中创建信号量和线程
int main(void)
{
    //初始化ThreadX
    tx_kernel_enter();
    //创建信号量,初始值为0
    tx_semaphore_create(&semaphore, "semaphore", 0);
    //创建线程1,优先级为10
    tx_thread_create(&thread1, "thread1", thread1_entry, 0, thread1_stack, 1024, 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START);
    //创建线程2,优先级为20
    tx_thread_create(&thread2, "thread2", thread2_entry, 0, thread2_stack, 1024, 20, 20, TX_NO_TIME_SLICE, TX_AUTO_START);
    //启动ThreadX
    tx_kernel_exec();
    //永远不会到达这里
    return 0;
}

上面的代码中,线程1每隔一段时间就会发送一个信号量,表示某个事件已经发生;线程2则会一直等待信号量,表示等待事件的发生。当线程1发送信号量后,线程2就会被唤醒,然后做一些工作,这样就实现了两个线程的同步。

信号量的任务通知

ThreadX中的信号量还有一个高级的功能,就是信号量的任务通知,也称为事件链。信号量的任务通知可以用来将多个信号量连接在一起,实现更复杂的同步机制。信号量的任务通知的原理是,当一个线程获取或释放一个信号量时,可以注册一个回调函数,该回调函数会在信号量的值发生变化时被调用,从而可以对其他的信号量进行操作。例如,下面的代码演示了如何使用信号量的任务通知来实现一个生产者-消费者模型:

//定义一个队列,用来存放生产的数据
TX_QUEUE queue;
UCHAR queue_buffer[100];

//定义两个信号量,用来表示队列的空闲空间和已用空间
TX_SEMAPHORE empty;
TX_SEMAPHORE full;

//定义一个信号量的任务通知回调函数,用来在队列满时释放full信号量,在队列空时释放empty信号量
void queue_notify(TX_SEMAPHORE *semaphore_ptr)
{
    //获取队列的信息
    ULONG messages, empty_slots;
    tx_queue_info_get(&queue, NULL, &messages, &empty_slots, NULL, NULL);
    //如果队列满了,释放full信号量
    if (messages == 100)
    {
        tx_semaphore_put(&full);
    }
    //如果队列空了,释放empty信号量
    if (empty_slots == 100)
    {
        tx_semaphore_put(&empty);
    }
}
//定义两个线程的入口函数,一个是生产者,一个是消费者
void producer_entry(ULONG entry_input)
{
    while(1)
    {
        //生成一个随机数,作为生产的数据
        ULONG data = rand();
        //获取empty信号量,表示占用一个空闲空间
        tx_semaphore_get(&empty, TX_WAIT_FOREVER);
        //将数据发送到队列中
        tx_queue_send(&queue, &data, TX_NO_WAIT);
        //注册信号量的任务通知回调函数,用来在队列满时释放full信号量
        tx_semaphore_info_set_notify(&empty, queue_notify);
        //延时一段时间
        tx_thread_sleep(50);
    }
}

void consumer_entry(ULONG entry_input)
{
    while(1)
    {
        //获取full信号量,表示消费一个已用空间
        tx_semaphore_get(&full, TX_WAIT_FOREVER);
        //从队列中接收数据
        ULONG data;
        tx_queue_receive(&queue, &data, TX_NO_WAIT);
        //注册信号量的任务通知回调函数,用来在队列空时释放empty信号量
        tx_semaphore_info_set_notify(&full, queue_notify);
        //处理数据
        //...
    }
}

//定义两个线程的控制块和栈空间
TX_THREAD producer;
TX_THREAD consumer;
UCHAR producer_stack[1024];
UCHAR consumer_stack[1024];

//在主函数中创建信号量,队列和线程
int main(void)
{
    //初始化ThreadX
    tx_kernel_enter();
    //创建两个信号量,初始值分别为100和0
    tx_semaphore_create(&empty, "empty", 100);
    tx_semaphore_create(&full, "full", 0);
    //创建一个队列,容量为100
    tx_queue_create(&queue, "queue", TX_1_ULONG, queue_buffer, 100);
    //创建生产者线程,优先级为10
    tx_thread_create(&producer, "producer", producer_entry, 0, producer_stack, 1024, 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START);
    //创建消费者线程,优先级为20
    tx_thread_create(&consumer, "consumer", consumer_entry, 0, consumer_stack, 1024, 20, 20, TX_NO_TIME_SLICE, TX_AUTO_START);
    //启动ThreadX
    tx_kernel_exec();
    //永远不会到达这里
    return 0;
}

上面的代码中,生产者线程每隔一段时间就会生成一个随机数,并发送到队列中,同时获取empty信号量,表示占用一个空闲空间;消费者线程则会从队列中接收数据,并获取full信号量,表示消费一个已用空间。当队列满或空时,信号量的任务通知回调函数会被调用,从而释放相应的信号量,唤醒等待的线程。这样,信号量的任务通知就可以用来实现一个生产者-消费者模型,保证队列的正确操作。

信号量的注意事项

在使用信号量时,有一些注意事项需要遵守,以避免出现错误或死锁的情况:

  • 不要在中断服务例程中调用信号量的函数,因为这可能会导致线程的调度,而中断服务例程不允许线程的切换。
  • 不要在临界区中调用信号量的函数,因为这可能会导致线程的阻塞,而临界区不允许线程的阻塞。
  • 不要在持有互斥锁的情况下调用信号量的函数,因为这可能会导致线程的挂起,而互斥锁不允许线程的挂起。
  • 不要在同一个线程中多次获取同一个信号量,因为这可能会导致线程的死锁,除非信号量是可重入的。
  • 不要在不同的线程中释放同一个信号量,因为这可能会导致信号量的值溢出,除非信号量是可溢出的。
  • 不要在没有获取信号量的情况下释放信号量,因为这可能会导致信号量的值错误,除非信号量是可释放的。

信号量的扩展功能

ThreadX还提供了一些信号量的扩展功能,用来满足更多的需求,这些功能包括:

  • 可重入信号量:允许同一个线程多次获取同一个信号量,而不会导致死锁,通过函数tx_semaphore_prioritize来设置。
  • 可溢出信号量:允许不同的线程多次释放同一个信号量,而不会导致溢出,通过函数tx_semaphore_info_set_notify来设置。
  • 可释放信号量:允许在没有获取信号量的情况下释放信号量,而不会导致错误,通过函数tx_semaphore_performance_info_get来设置。
  • 优先级继承信号量:允许在获取信号量的线程被阻塞时,将其优先级提升到等待信号量的最高优先级的线程,从而避免优先级反转的问题,通过函数tx_semaphore_performance_system_info_get来设置。

信号量的性能分析

ThreadX还提供了一些信号量的性能分析的函数,用来获取信号量的使用情况和统计信息,这些函数包括:

  • tx_semaphore_info_get:获取信号量的名称,当前值,等待线程的数量,等待线程的列表,信号量的任务通知回调函数等信息。
  • tx_semaphore_performance_info_get:获取信号量的总的获取次数,总的释放次数,总的超时次数,总的等待线程的数量,最大的等待线程的数量等信息。
  • tx_semaphore_performance_system_info_get:获取系统中所有信号量的总数,当前活动的信号量的数量,当前等待信号量的线程的数量,最大的等待信号量的线程的数量等信息。

信号量的总结

信号量是一种常用的线程间同步和资源管理的机制,它可以用来表示信号对象或资源的数量。在ThreadX中,信号量是一个32位的计数值,它可以通过函数tx_semaphore_create创建,并指定一个初始值。信号量的值可以通过函数tx_semaphore_get和tx_semaphore_put来增加或减少,从而实现线程间的协调和通信。信号量还有一些高级的功能,如信号量的任务通知,信号量的扩展功能,信号量的性能分析等,用来满足更多的需求。信号量是ThreadX中的一个重要的组件,它可以用来实现多种复杂的同步机制,如生产者-消费者模型,读者-写者模型,哲学家就餐问题等。

【01】初识ThreadX 简介 ThreadX是一个成熟的商用硬实时嵌入式操作系统,被广泛应用于消费电子、航空航天、通信、工业控制与医疗等应用领域中,至今已服务超过62亿设备。它以轻量级的规模,提供了良好的实时性、可靠性与易用性,是嵌入式开发中不错的RTOS选择。凭借良好的发展势头,其母公司Express Logic于2019年被微软收购。 技术上,ThreadX RTOS提供了高级调度、通信、同步、定时器、内存... 阅读详情

相关推荐

threadx学习笔记(6)信号量

semaphore意为信号量有两种操作会影响计数信号量的值:tx_semaphore_get和tx_semaphore_put。get操作将信号量减少1。如果信号量为0,则get操作失败。与get操作相反的是put操作,它将信号量增加1。

m0_71240643的博客 1395

实时操作系统ThreadX全中文手册上线了

关注+星标公众号,不错过精彩内容作者 | strongerHuang微信公众号|嵌入式专栏对于很多初学者来说,学习一门技术非常头疼的一件事,就是面对英文资料和手册。不但初学者,对于有一...

strongerHuang 1万+

ThreadX学习(6)——信号量

ThreadX学习(6)——信号量学习参考信号量二值信号量事件通知API1.tx_semaphore_create2.tx_semaphore_delete3.tx_semaphore_get4.tx_semaphore_info_get5.tx_semaphore_prioritize6.tx_semaphore_put 学习参考 《Real-Time Embedded Multithreading: Using ThreadX and ARM》 (链接:https://pan.baidu.com/s/

weixin_43739110的博客 1480

ThreadX_笔记

安富莱_STM32-v7开发板ThreadX内核教程——笔记1.ThreadX--任务管理1.1 裸机-栈1.2 RTOS--栈1.3 MSP、PSP1.4 实际应用中系统栈空间分配多大?1.5 ThrreadX 的任务状态1.6 ThreadX 启动流程2.栈大小及溢出2.1 任务栈大小的确定2.2 ThrreadX 的栈溢出检测机制2.2.1 实现原理2.2.2 实现方法3.ThrreadX 中断优先级配置,含 BasePrrii 配置方案 1.ThreadX–任务管理 1.1 裸机-栈      管

oDuanYanGuHong的博客 3946

ThreadX(六)------信号量semaphore

信号量semphere概述APItx_semaphore_createtx_semaphore_deletetx_semaphore_gettx_semaphore_puttx_semaphore_put_notifysemaphore_demo 概述 ThreadX提供32位计数信号量,范围在0到4,294,967,295之间。 有两种用于计数信号量的操作:tx_semaphore_get和tx_semaphore_put。 get操作将信号量减一。 如果信号量为0,则get操作不会成功。 与get操作相

heartbeats的博客 3098

2022-01-16 threadx的信号量的应用

实验使用的开发板是ART-PI,stm32h750芯片+threadx。 第一步:首先通过stm32cubeMX移植了threadx(参考上一篇文章)。 第二步:创建信号量。在 int tx_application_define(VOID *first_unused_memory)里面创建信号量。 //创建信号量 UINT status; status=tx_semaphore_create((TX_SEMAPHORE *) &Semaphore,"semaphore

Believeziwo的博客 2933

2、ThreadX 操作系统

ThreadX几乎是小型RTOS的巅峰之作,不管你之前用的那个OS,如果有精力建议还是学习下。62亿电子设备采用,是其它RTOS无法逾越的高山。

oDuanYanGuHong的博客 2060

深入解析ThreadX任务管理:函数探秘

在实时嵌入式系统开发中,ThreadX作为一种可靠、高效的实时操作系统(RTOS),其任务管理功能备受开发者青睐。通过合理使用上述ThreadX任务管理函数,开发者可以实现任务的创建、调度、挂起、终止和睡眠等操作。通过指定任务的入口函数、堆栈大小、优先级等参数,该函数将为任务分配必要的资源并将其加入到任务列表中。任务终止后,所占用的资源将被释放,并且不再参与调度。当然,ThreadX还有更多功能丰富的任务管理函数,如互斥锁、定时器等,可以根据具体需求进行使用。函数可恢复被挂起的任务,使其重新参与调度。

小灰灰的博客 1389

ThreadX 信号量

THREADX 信号量

jingling122的博客 1361

Threadx 信号量semaphore

文章目录信号量控制块信号量队列信号量API优先级翻转信号量创建_tx_semaphore_create删除信号量_tx_semaphore_delete 信号量(semaphore)用来保护共享资源,临界区访问,同步;可以用于生产者-消费者模式中提供事件通知。 如果信号量计数器最大为1,其值可能为0或1,成为二进制信号量。二进制信号量作用类似互斥量,但信号量不支持所有权,不支持优先级继承。 信号量...

osnet的博客 1255

PCIe5.0均衡简介(整理版)

pcie5.0 均衡 equalization

m0_53559277的博客 9108

ThreadX 互斥信号量

threadx 互斥信号量

jingling122的博客 1159

手把手教你用8位单片机IO口直接驱动WS2812灯带(附完整代码和避坑指南)

本文详细介绍了如何使用8位单片机IO口直接驱动WS2812灯带,包括硬件准备、时序生成、色彩引擎与特效算法的实现,以及调试技巧与性能优化。通过汇编语言优化和精确时序控制,实现高效的LED驱动和炫酷的彩虹灯效,适合嵌入式开发者和硬件爱好者参考。

weixin_42696271的博客 304

threadx 信号量 应用_ThreadX——IPC应用之信号量

一、应用简介在RTOS的应用开发中,信号量也是经常使用到的一种用于多任务之间信息同步、资源互斥访问的一种手段,常用于协调多个任务访问同一资源的场景。信号量又分为计数信号量和互斥信号量。计数信号量可以表示整体资源数量,当获取一个资源后计数信号量减一,释放一个资源后计数信号量加一,当信号量为0时即表明资源被全部分配导致无法再获取资源,任务可以挂起等待直到有资源可用。互斥信号量是可以理解为只能维护资源数...

weixin_39917791的博客 421

Context Capture10.20 安装教程(附安装包)

ContextCapture 是一款由Bentley公司推出的实景建模软件,可以快速为各种类型的基础设施项目生成最具挑战性的反应现实环境的三维模型。

一起来交流学习吧 2万+

采用MPU6050的手势遥控器

随着社会的发展与进步,电子产品日益更新,个人家庭迎来了越来越多的智能家电。然而,现在的智能电子设备产品的遥控器多数都是按键形的。操作繁琐不直观,学习成本大。并且对于有老人小孩的家庭,给他们的操作带来了巨大的障碍。手势遥控器是指利用简单的手势来指挥电子设备,获得便捷的操作体验。让家庭成员都可以享受科技发展带来的福利。MPU6050是一个运动传感器,内置陀螺仪,再由电子设备利用判断结果做出相应的响应即...

Sakura的博客小站 6602

【STM32F429】第20章 ThreadX互斥信号量

论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514 第20章 ThreadX互斥信号量 本章节讲解ThreadX的资源共享机制---互斥信号量(Mutex,即Mutual Exclusion的缩写)。注意,建议初学者学习完前两个章节的信号量后再学习本章节的互斥信号量。 目录 20.1 互斥信号量 20.1.1 互斥信号量的概念及其作用 20.1.2 优先级翻转问题...

Simon223的博客 1408

PyQt5 + HFSS:给你的仿真脚本做个专属GUI界面(零基础搭建指南)

本文详细介绍了如何使用PyQt5为HFSS仿真脚本创建专属GUI界面,适合零基础用户快速上手。通过Python二次开发,实现参数可视化调整、进度实时监控等功能,大幅提升团队协作效率。文章涵盖环境配置、界面设计、HFSS集成到打包部署的全流程,是仿真工程师提升工作效率的实用指南。

weixin_42535720的博客 185

ThreadX中使用信号量(基于启明欣欣开发板)

ThreadX中使用信号量

爱就是是恒久忍耐的专栏 961

​基于stm32的智能空气加湿器设计(含源代码和Proteus仿真)

课程设计分享

LoongSTUDIO的博客 2927

【深度学习|地学应用】MODIS AOD产品和HYSPLIT模型的局限性和不确定性?

【深度学习|地学应用】MODIS AOD产品和HYSPLIT模型的局限性和不确定性?

985小水博的摸鱼日常 462

【STM32F429】第19章 ThreadX信号量

论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514 第19章 ThreadX信号量 本章节开始讲解ThreadX的另一个重要的任务间的同步和资源共享机制,信号量。 目录 19.1 信号量 19.1.1 信号量的概念及其作用 19.1.2 ThreadX信号量原理 19.1.3 ThreadX任务间信号量的实现 19.1.4 Thre...

Simon223的博客 1168

YOLOv11【第二章:核心模块进阶篇·第3节】LDConv线性可变形卷积改进YOLOv11!

🏆 本文收录于专栏 《YOLOv11实战:从入门到深度优化》。本专栏围绕 YOLOv11 的改进、训练、部署与工程优化 展开,系统梳理并复现当前主流的 YOLOv11 实战案例与优化方案,内容目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。

**My Coding Family** 7440

threadx 信号量 应用_threadx学习笔记(二)

tx_kernel_enter();进入threadx核tx_kernel_enter()void tx_kernel_enter(void)所属文件调用者开关量demo.C启动代码无操作系统首先从从量表直接进入该函数,在函数以前没有进行任何的硬件及软件的初始化!该函数主要包含_tx_initialize_low_level(),_tx_initialize_hig...

weixin_42510608的博客 797

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

threadx 信号量 应用_THREADX操作系统各模块详解第一部分

THREADX深入学习简介最近在做THREADX移植项目,所以在开始学习THREADX操作系统。想把自己学到的东西总结一下。学习操作系统时,按照领导的意思把操作系统进行模块划分。通过查找资料将操作系统划分为任务调度模块、任务管理模块、任务间同步和通信模块、内存管理模块、中断管理模块、时钟管理模块。下面将分别对各个模块进行分析和研究。我将深入介绍各个模块的工作原理,通过此文档能对操作系统的工作原理有...

weixin_39688636的博客 357

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: ThreadX_note:创建线程
下一篇: ThreadX:怎么确定一个线程应该开多少内存
DennisReYoonjiho
博客等级 码龄7年 216粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值