Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread
内核学习
僵尸线程
RT-Thread 内核学习笔记 - 理解defunct僵尸线程
发布于 2021-02-28 13:56:48 浏览:1656
订阅该版
[tocm] [RT-Thread 入门学习笔记 - 目录](https://club.rt-thread.org/ask/article/3420.html) [RT-Thread 内核学习笔记 - 内核对象rt_object](https://club.rt-thread.org/ask/article/2493.html) [RT-Thread 内核学习笔记 - 内核对象管理](https://club.rt-thread.org/ask/article/2494.html) [RT-Thread 内核学习笔记 - 内核对象操作API](https://club.rt-thread.org/ask/article/2513.html) [RT-Thread 内核学习笔记 - 内核对象初始化链表组织方式](https://club.rt-thread.org/ask/article/2522.html) [RT-Thread 内核学习笔记 - 内核对象链表结构深入理解](https://club.rt-thread.org/ask/article/2549.html) [RT-Thread 内核学习笔记 - 设备模型rt_device的理解](https://club.rt-thread.org/ask/article/2570.html) [RT-Thread 内核学习笔记 - 理解defunct僵尸线程](https://club.rt-thread.org/ask/article/2580.html) ## 前言 - 目前大家偶尔会讨论RT-Thread线程退出的问题,如main线程`return`后,怎么处理的?占用的内存`RAM`资源是否得到释放。 - 最近在看线程相关的内核源码,基于内核对象rt_object管理方法,梳理一下线程退出后的处理流程。 - rt_thread_defunct,僵尸线程的链表结构,为什么叫【僵尸】,我查的字典,作用就是回收删除的线程的内存(堆)资源。 ## 线程初始化与创建 - rt_thread_init:静态初始化一个线程,线程结构体、线程栈,都是全局的变量。rt_thread_detach后,这个线程的内核对象从内核容器链表里移除,【但】线程结构体、线程栈,因为是静态全局的,无法释放。若下次再想初始化并使用这个线程,依旧可以使用这个detach后的现有的线程结构体、线程栈进行初始化。 - 静态线程的特点:初始化后,内存的占用就不会改变。 - rt_thread_create:动态创建一个线程。需要使能:RT_USING_HEAP,堆管理。创建的线程【结构体】与【线程栈】都是动态申请出来的。删除这个线程时,需要调用rt_thread_delete。删除后,线程的【结构式】与【线程栈】占用的内存(堆)空间,可以释放。删除后这个线程不存在了,想再次开启使用需要重新创建。 - 动态线程的特点:删除后,内存资源可以释放。 ## 线程的资源回收 - RT-Thread 只回收rt_thread_create的线程内存资源。 - 静态初始化或动态创建线程时,会注册:rt_thread_exit,线程退出后,会调用rt_thread_exit。 - rt_thread_exit中,第一步:把线程从调度链表移除。第二步:静态的线程,会调用:rt_object_detach,从内核对象容器里移除线程内核对象;动态线程,会把线程的结构体指针(操作句柄),加入rt_thread_defunct僵尸线程链表中,而不是立即释放线程占用的内存。僵尸线程的操作,是在idle线程中执行。第三步:执行线程调度,切换线程。在idle线程执行,应该是保证这个线程删除后,立即调度切换线程,线程的资源回收不需要太高的优先级。 - idle 线程中: rt_thread_idle_excute 负责查看rt_thread_defunct僵尸线程链表是否为空,如果不为空,则执行内存释放的操作。从线程链表移除、释放线程栈、释放内核结构体。注意,只有动态创建的线程,执行此操作。 ``` /* 来自:rt_thread_idle_excute 片段 */ /* remove defunct thread */ rt_list_remove(&(thread->tlist)); /* release thread's stack */ RT_KERNEL_FREE(thread->stack_addr); /* delete thread object */ rt_object_delete((rt_object_t)thread); ``` ## main线程退出 - 上面梳理了线程的退出,僵尸线程的处理流程,main线程的退出,基本上也可以梳理流程了 - 静态的main线程,未使能:RT_USING_HEAP,退出后,内存资源不会释放。 - 动态的main线程,使能了:RT_USING_HEAP后,退出后,内存资源得到释放。 - 实际对比内存资源的释放大小,发现,动态申请,会额外占用一点内存资源,如12字节,这部分在后面内存管理后再深入的梳理。 ## 动态线程的资源回收: RT_USING_HEAP main存在时:线程栈大小为2048 ``` msh >free total memory: 89568 used memory : 10656 maximum allocated memory: 10656 ``` main不存在时: ``` msh >free total memory: 89568 used memory : 8456 maximum allocated memory: 10656 ``` main的线程栈,return后的资源:`2200 Bytes`空间 ``` 2048 栈空间 + 12Byte(rt_malloc管理占用) 128Byte rt_thread结构体大小,sizeof(struct rt_thread) + 12Byte(rt_malloc管理占用,内核对象)。 合计:2048+12+128+12 = 2200。 ``` ## 注意事项 - 动态创建的线程,线程里动态创建的对象,在删除线程前,需要先手动删除创建的对象,释放内存 - 如动态线程里,内部申请了一块内存,退出线程前,需要释放掉。 - 如动态线程里,内部使用全局静态的消息队列,退出线程前,需要detach掉。 ## 总结 - 熟悉RT-Thread线程的初始化、创建、脱离(反初始化)、删除等操作。 - 熟悉动态创建的线程,删除后,加入僵尸线程链表,内存资源回收流程。 - 理解普通线程如main线程的退出流程。 - 带着问题后续继续研究以下知识点: - 调度器的工作流程,在哪里执行?如何运作? - 线程定时器,每个线程都会创建一个,线程删除后,定时器资源的回收流程。 ``` rt_thread_delete /* 线程的定时器,使用detach方式,定时器资源回收流程 */ rt_timer_detach(&(thread->thread_timer)); /* 定时器资源的回收流程 */ ``` - 创建线程时,我把线程的名字(name)改为RT_NULL,依旧可以正常的运行,但这样是否有影响? - rt_thread 结构体中:内核对象的链表用于加入内核对象容器,成员:tlist的工作流程。 - 历史问题:rt_thread结构体: ``` /** * Thread structure */ struct rt_thread { /* rt object */ char name[RT_NAME_MAX]; /**< the name of thread */ rt_uint8_t type; /**< type of object */ rt_uint8_t flags; /**< thread's flags */ #ifdef RT_USING_MODULE void *module_id; /**< id of application module */ #endif rt_list_t list; /**< the object list */ ``` 是否可以改为如下: ``` /** * Thread structure */ struct rt_thread { struct rt_object parent; /**< inherit from rt_object */ ```
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
809
被采纳
175
关注TA
发私信
相关文章
1
RT-THREAD在STM32H747平台上移植lwip
2
正点原子miniSTM32开发板读写sdcard
3
反馈rtt串口驱动对低功耗串口lpuart1不兼容的问题
4
Keil MDK 移植 RT-Thread Nano
5
RT1061/1052 带 RTT + LWIP和LPSPI,有什么坑要注意吗?
6
RT thread HID 如何收发数据
7
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
8
RT-Thread修改项目名称之后不能下载
9
rt-studio编译c++
10
有木有移植rt-thread(nano)到riscv 32位MCU上
推荐文章
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
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部