Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024-RSOC】 DAY2 关于线程的学习分享
发布于 2024-07-24 16:39:44 浏览:436
订阅该版
[tocm] # 【2024-RSOC】 DAY2 关于线程的使用和调度分析 ## 线程内核介绍 [RT-Thread线程管理文档](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/thread/thread) 此线程说明,为官方文档介绍。 ## 线程示例 此笔记精讲该示例的代码形式: 这个例子创建一个动态线程初始化两个静态线程,动态线程一直重复红灯亮灭的过程。 ```c #include
#include
#include
#define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 5 #define GPIO_LED_A GET_PIN(F, 11) #define GPIO_LED_B GET_PIN(F, 12) static rt_thread_t tid1 = RT_NULL; /* 线程1的入口函数 */ static void thread1_entry(void *parameter) { rt_uint32_t count = 0; rt_pin_mode(GPIO_LED_A, PIN_MODE_OUTPUT); while (1) { rt_kprintf("红灯亮\n"); rt_pin_write(GPIO_LED_B, PIN_LOW); rt_thread_mdelay(1000); rt_kprintf("红灯亮完\n"); rt_pin_write(GPIO_LED_B, PIN_HIGH); rt_thread_mdelay(2000); } } #ifdef rt_align rt_align(RT_ALIGN_SIZE) #else ALIGN(RT_ALIGN_SIZE) #endif static char thread2_stack[1024]; static struct rt_thread thread2; /* 线程2入口 */ static void thread2_entry(void *param) { rt_uint32_t count = 0; rt_pin_mode(GPIO_LED_B, PIN_MODE_OUTPUT); /* 线程2拥有较高的优先级,以抢占线程1而获得执行 */ for (count = 0; count < 10 ; count++) { rt_kprintf("绿灯亮\n"); rt_pin_write(GPIO_LED_A, PIN_LOW); rt_thread_mdelay(2000); rt_kprintf("绿灯亮完红灯亮\n"); rt_pin_write(GPIO_LED_A, PIN_HIGH); rt_thread_mdelay(2000); } rt_kprintf("thread2 exit\n"); /* 线程2运行结束后也将自动被系统脱离 */ } static char thread3_stack[1024]; static struct rt_thread thread3; /* 线程3入口 */ static void thread3_entry(void *param) { rt_uint32_t count = 0; /* 线程3拥有较高的优先级,以抢占线程1而获得执行 */ for (count = 0; count < 10 ; count++) { /* 线程3打印计数值 */ rt_kprintf("QAQ 亮不完啦!: (%d)\n", count); rt_thread_mdelay(8000); } rt_kprintf("thread3 exit\n"); /* 线程3运行结束后也将自动被系统脱离 */ } /* 线程示例 */ int thread_sample(void) { /* 创建线程1,名称是thread1,入口是thread1_entry*/ tid1 = rt_thread_create("thread1", thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); #ifdef RT_USING_SMP /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */ rt_thread_control(tid1, RT_THREAD_CTRL_BIND_CPU, (void*)0); #endif /* 如果获得线程控制块,启动这个线程 */ if (tid1 != RT_NULL) rt_thread_startup(tid1); /* 初始化线程2,名称是thread2,入口是thread2_entry */ rt_thread_init(&thread2, "thread2", thread2_entry, RT_NULL, &thread2_stack[0], sizeof(thread2_stack), THREAD_PRIORITY - 1, THREAD_TIMESLICE); #ifdef RT_USING_SMP /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */ rt_thread_control(&thread2, RT_THREAD_CTRL_BIND_CPU, (void*)0); #endif rt_thread_startup(&thread2); /* 初始化线程3,名称是thread3,入口是thread3_entry */ rt_thread_init(&thread3, "thread3", thread3_entry, RT_NULL, &thread3_stack[0], sizeof(thread3_stack), THREAD_PRIORITY - 2, THREAD_TIMESLICE); #ifdef RT_USING_SMP /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */ rt_thread_control(&thread3, RT_THREAD_CTRL_BIND_CPU, (void*)0); #endif rt_thread_startup(&thread3); return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(thread_sample, thread sample); int main (void) { return 0; } ``` ## 代码精讲 线程1为动态线程: ```c /* 线程1的入口函数 */ static void thread1_entry(void *parameter) { rt_uint32_t count = 0; while (1) { /* 线程1采用低优先级运行,一直打印计数值 */ rt_kprintf("thread1 count: %d\n", count ++); rt_thread_mdelay(500); } } ``` #### 线程的入口函数 线程控制块中的 entry 是线程的入口函数,它是线程实现预期功能的函数。线程的入口函数由用户设计实现。一般有以下两种代码形式,而线程1即为两种模式的集合。 **无限循环模式:** 在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外界事件的发生,而后进行相应的服务: ```c void thread1_entry(void *parameter) { while (1) { /* 等待事件的发生 */ /* 对事件进行服务、进行处理 */ } } ``` 注意:线程中不能陷入死循环操作,必须要有让出 CPU 使用权的动作,如循环中调用延时函数或者主动挂起。 用户设计这种无限循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。 **顺序执行或有限次循环模式:** 如简单的顺序语句、do while() 或 for()循环等,此类线程不会循环或不会永久循环,可谓是 “一次性” 线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。 ```c static void thread1_entry(void *parameter) { rt_kprintf("红灯亮\n"); /* 事件1 */ rt_pin_write(GPIO_LED_B, PIN_LOW); rt_thread_mdelay(1000); //延时1000ms rt_kprintf("红灯亮完\n"); /* 事件2 */ rt_pin_write(GPIO_LED_B, PIN_HIGH); rt_thread_mdelay(2000); } ``` 线程2为静态线程:静态线程线程在运行完毕后自动被系统删除,即当count=10; ```c /* 线程2入口 */ static void thread2_entry(void *param) { rt_uint32_t count = 0; rt_pin_mode(GPIO_LED_B, PIN_MODE_OUTPUT); /* 线程2拥有较高的优先级,以抢占线程1而获得执行 */ for (count = 0; count < 10 ; count++) { rt_kprintf("绿灯亮\n"); rt_pin_write(GPIO_LED_A, PIN_LOW); rt_thread_mdelay(2000); rt_kprintf("绿灯亮完红灯亮\n"); rt_pin_write(GPIO_LED_A, PIN_HIGH); rt_thread_mdelay(2000); } rt_kprintf("thread2 exit\n"); /* 线程2运行结束后也将自动被系统脱离 */ } ``` #### 线程的重要属性 #### 线程优先级 ```c #define THREAD_PRIORITY 25 ``` 初始设计优先级为25 即线程1的优先级为25 ```c int thread_sample(void) { /* 创建线程1,名称是thread1,入口是thread1_entry*/ tid1 = rt_thread_create("thread1", thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); #ifdef RT_USING_SMP /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */ rt_thread_control(tid1, RT_THREAD_CTRL_BIND_CPU, (void*)0); #endif /* 如果获得线程控制块,启动这个线程 */ if (tid1 != RT_NULL) rt_thread_startup(tid1); ``` 而线程2的优先级为 THREAD_PRIORITY-1 = 25 - 1 = 24 所以线程2优先于线程1 ```c /* 初始化线程2,名称是thread2,入口是thread2_entry */ rt_thread_init(&thread2, "thread2", thread2_entry, RT_NULL, &thread2_stack[0], sizeof(thread2_stack), THREAD_PRIORITY - 1, THREAD_TIMESLICE); #ifdef RT_USING_SMP /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */ rt_thread_control(&thread2, RT_THREAD_CTRL_BIND_CPU, (void*)0); #endif rt_thread_startup(&thread2); ``` 因为线程2绿灯亮起的延时是线程1红灯亮起的二倍,同理线程3: ![Snipaste_2024-07-24_16-35-56.jpg](https://oss-club.rt-thread.org/uploads/20240724/21b38b655e165e9ea3872385ff1d8aa1.jpg.webp) 命令: ```c /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(thread_sample, thread sample); ``` ![Snipaste_2024-07-24_16-36-16.jpg](https://oss-club.rt-thread.org/uploads/20240724/1b9f30ff4f20eb6e106c0195be219435.jpg.webp)
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
cy_99
这家伙很懒,什么也没写!
文章
3
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
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组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
SFUD
msh
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
549
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部