Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
信号量_semaphore
遇到一个信号量的问题
发布于 2023-04-23 19:52:37 浏览:804
订阅该版
我创建了两个线程,一个线程释放信号量,一个线程获取信号量,获取信号量的优先级要高些,也就意味着,低优先级的线程一释放信号量,高优先级的能获取到信号量,但是事实上他却是低优先级的线程释放完了信号量,任务二才开始执行,只有在使用finsh的时候才会这样,如果写在主函数就不会。这个是官方变成指南的例程代码。 ![bbcf7d2398bd80405cadeeb5806377d.png](https://oss-club.rt-thread.org/uploads/20230423/4bda625165d418b798be7c5403ba8c32.png) ![596b2836c5db18cf51b6c08fb571f80.png](https://oss-club.rt-thread.org/uploads/20230423/467da4050b95809f14733702d88097f2.png) 上面是在命令行运行的代码,下面是在main运行的代码和结果 ![c97df2445b2b46679f2ce33d7e79ba5.png](https://oss-club.rt-thread.org/uploads/20230423/0969e7a63f0c8ce775ce19c15e95cf1c.png) ![64d46ef28ec006af877935d6da267bd.png](https://oss-club.rt-thread.org/uploads/20230423/88cd7e15ae0ac99be290b06ea17726b9.png)
查看更多
4
个回答
默认排序
按发布时间排序
lchnu
2023-04-23
Witness, Understand, Skill
`RT-Thread运行处于就绪态的最高优先级线程。` 按照你的设置,且假设timer线程不存在的情况下(存在与否,对你的结果没有影响),线程优先级从高到低,分别是 > demo_02,为9;demo_01, main,均为10;tshell,为20 **在Finsh中调用single函数** 1. tshell线程的优先级是20。single函数是优先级为20的tshell线程中调用的。 2. rt_thread_init创建线程后,两个线程的状态都是INIT状态,而不是就绪态 3. single函数使用startup(&tid)后,将demo_01变成就绪,demo_01剥夺tshell线程的CPU使用权 4. demo_01中release信号量后,会进行线程切换,但是demo_01依然是处于`就绪态的最高优先级任务`,不会释放CPU 5. demo_01运行10次,退出了线程,CPU使用权依次交回给main -> tshell线程 6. tshell线程运行startup(&tid2),将demo_02变成就绪,demo_02剥夺tshell线程的CPU使用权 7. demo_02运行10次,每次都能take成功信号量 **将single函数的内容写入到main线程中** 1. main线程的优先级是10 2. rt_thread_init创建线程后,两个线程的状态都是INIT状态,而不是就绪态 3. main线程使用startup(&tid)后,将demo_01变成就绪。但因为它和main是同优先级,main线程没有任何放弃CPU的行为,所以,CPU使用权不会从main中交出去 4. main线程继续startup(&tid)后,将demo_02变成就绪。由于demo_02的优先级是9,高于main,所以demo_02剥夺main线程的CPU使用权 5. demo_02打印task 02 demo,take信号量,没有信号量release,demo_02从就绪态变成Suspend状态,交出CPU使用权 6. demo_01拿到CPU使用权,打印task 01 demo, 释放1次信号量,且产生线程切换到demo_02 7. demo_01和demo_02交替打印 下方有个链接,是前几天我对相同问题的回复,供参考。 https://club.rt-thread.org/ask/question/d59eb4f4fa9c5a3e.html 在论坛中交流,建议养成贴代码的习惯,更方便大家交流沟通。 我在下方给你贴的代码中,添加了调度器的钩子函数,你可以更加清晰地从输出信息中看到线程切换过程。 ```c /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-04-23 lchnu first version */ #include
#define DBG_TAG "main" #define DBG_LVL DBG_LOG #include
#define SEMAPHORE_DEMO_IN_MAIN rt_sem_t dynamic_sem; void thread_demo_01(void *arg) { static rt_uint8_t count = 0; rt_kprintf("thread1 demo\n"); while (1) { if (count <= 100) { count++; } else return; /* count 每计数 10 次,就释放一次信号量 */ if (0 == (count % 10)) { rt_kprintf("t1 release a dynamic semaphore.\n"); rt_sem_release(dynamic_sem); } } } void thread_demo_02(void *arg) { static rt_err_t result; static rt_uint8_t number = 0; rt_kprintf("thread2 demo\n"); while (1) { /* 永久方式等待信号量,获取到信号量,则执行 number 自加的操作 */ result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER); if (result != RT_EOK) { rt_kprintf("t2 take a dynamic semaphore, failed.\n"); rt_sem_delete(dynamic_sem); return; } else { number++; rt_kprintf("t2 take a dynamic semaphore. number = %d\n", number); } } } static void hook_of_scheduler(struct rt_thread* from, struct rt_thread* to) { rt_kprintf("from: %s --> to: %s \n", from->name , to->name); } int main(void) { #ifdef SEMAPHORE_DEMO_IN_MAIN rt_thread_t tid1, tid2; rt_scheduler_sethook(hook_of_scheduler); dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO); tid1 = rt_thread_create("thread1", thread_demo_01, RT_NULL, 1024, 10, 20); tid2 = rt_thread_create("thread2", thread_demo_02, RT_NULL, 1024, 9, 20); rt_thread_startup(tid1); rt_thread_startup(tid2); #endif return RT_EOK; } #ifndef SEMAPHORE_DEMO_IN_MAIN int single(int argc, char *argv[]) { rt_thread_t tid1, tid2; rt_scheduler_sethook(hook_of_scheduler); dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO); tid1 = rt_thread_create("thread1", thread_demo_01, RT_NULL, 1024, 10, 20); tid2 = rt_thread_create("thread2", thread_demo_02, RT_NULL, 1024, 9, 20); rt_thread_startup(tid1); rt_thread_startup(tid2); return 0; } MSH_CMD_EXPORT(single, test semaphore); #endif ``` 最后,你可以尝试一下,**使用Finsh方式创建两个线程,但是将demo_01的优先级从10改成25,得到的结果就和官方例程一样了。** ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230423/389f47279d32b36dacb086f1c0a1033f.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230423/6769da3e6554c6247c1cc7812966d898.png.webp)
winfeng
认证专家
2023-04-23
这家伙很懒,什么也没写!
贴完整的代码,不能只描述;
张世争
2023-04-24
学以致用
把 shell 线程的优先级调高,比如 0~10。现象不同时 shell 线程本身优先级问题
yangjie
认证专家
2023-04-24
hello
main和shell优先级不同,在低优先级(20)的shell中,启动高优先级线程(9/10)就会马上抢占cpu运行的。
撰写答案
登录
注册新账号
关注者
0
被浏览
804
关于作者
LuckRH
这家伙很懒,什么也没写!
提问
4
回答
0
被采纳
0
关注TA
发私信
相关问题
1
怎样可以将信号量复位为初始值
2
rt_sem_take 引起段错误
3
生产者消费者中是否可以使用一个事件集来代替多个二值信号量?
4
看RTT文档,不太懂有关信号量的死锁问题
5
这样使用UART接收一帧数据的方法是否可行
6
一对多线程间通信的问题
7
动态内存堆 保护全局变量lfree,为什么用信号量而不是互斥信号量
8
二值信号量的使用问题
9
USART1_IRQHandler串口中断接收问题
10
开发文档semaphore_sample.c有问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
组件 lwip v2.0.3 版本使用 netdev网卡的 ping 功能
2
简单两步配置RTT源码阅读环境 vsc+clangd
3
恩智浦[FRDM-MCXN947]初探 之 ADC与DAC
4
LVGL使用字库IC芯片显示中文
5
基于STM32H750和Rt-Thread的CANFD通信实现的记录(一)
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
线程
RT-Thread Nano
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
807
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部