线程相关的"/>
线程相关的
1.线程通常定义为具有专用用途的半独立程序段,所有线程的组合构成了应用程序。
2.线程在初始化或线程执行期间通过tx_thread_create来动态创建。创建的线程处于“就绪”或“已挂起”状态。
3.线程状态
ThreadX有五个不同的线程状态:就绪(Ready)、已挂起(Suspended)、正在执行(Executing)、已终止(Terminated)、已完成(Completed)。
(1) 就绪
线程准备好执行时处于Ready
(2) 正在执行
在处于Ready的线程中,只有优先级最高的就绪线程才会执行。执行时,状态更改为Executing
任意时刻,只有一个线程处于Executing。处于该状态的线程可以控制基础处理器
(3) 已挂起
处于Suspended的线程不符合执行条件。导致Suspended的原因包括:挂起时间、队列消息、信号灯、互斥、事件标志、内存和基本线程挂起。排除导致挂起的原因后,线程将恢复Ready
(4) 已完成
已完成其处理任务并从entry函数返回的线程。entry函数在线程创建期间指定。处于Completed的线程无法再次执行
(5) 已终止
当另一个线程或该线程本身调用了tx_thread_terminate服务,线程处于Terminated。处于Terminated的线程无法再次执行
注:若需重新启动Completed或Terminated的线程,应用程序必须先删除该线程,然后重新创建并重新启动该线程。
4.线程进入/退出通知
通过tx_thread_entry_exit_notify实现。
为特定线程注册应用程序通知函数,ThreadX 会在该线程开始运行、完成或终止时调用该函数。 应用程序通知函数在调用后可以执行特定于应用程序的处理。 这通常涉及通过 ThreadX 同步基元通知此事件的另一个应用程序线程。
5.线程控制块TX_THREAD
每个线程的特征包含在其控制块中,此结构在tx_api.h中定义。
线程的控制块可以位于内存中的任意位置,但最常见的是通过在任何函数的作用域外部定义该控件块来使其成为全局结构。
调试时有用的参数:
(1) tx_thread_run_count
包含记录线程已调用次数的计数器。 计数器增加表示正在调度和执行线程。
(2) tx_thread_state
包含相关线程的状态(TX_READY、TX_COMPLETED、TX_TERMINATED、TX_SUSPENDED、 TX_SLEEP、TX_QUEUE_SUSP、TX_SEMAPHORE_SUSP、TX_EVENT_FLAG、TX_BLOCK_MEMORY、TX_BYTE_MEMORY、TX_MUTEX_SUSP)
6.当前Executing线程
调用 tx_thread_identify,程序段可以获取正在执行的线程的控制块地址。
用户可以检查 ThreadX 内部指针 _tx_thread_current_ptr。 该数组包含当前正在执行的线程的控制块地址。 如果此指针为 NULL,则不执行任何应用程序线程;也就是说,ThreadX 在其调度循环中等待线程准备就绪。
7.线程堆栈区域
(1) 功能
每个线程都有自己的堆栈,在内存中的位置取决于应用程序,在线程创建期间指定,用于保存其上次执行和编译器使用的上下文。 可将重要线程堆栈置于高速 RAM 中来提高线程的性能。
(2) 大小
最小堆栈大小 TX_MINIMUM_STACK 由 ThreadX 定义。 支持保存线程的上下文、最少量的函数调
用和局部变量分配。
可以调整线程堆栈大小。tip:在创建线程之前,使用诸如 (0xEFEF) 等易于识别的数据模式预设所有堆栈区域。默认情况下,ThreadX 使用值 0xEF 初始化每个线程堆栈的每个字节
(3) 运行时堆栈检查
TX_ENABLE_STACK_CHECKING检查每个线程的堆栈是否因为线程挂起或恢复而损坏。如果检测到堆栈损坏,ThreadX 将调用在调用 tx_thread_stack_error_notify 时指定的应用程序堆栈错误处理例程。如果未指定堆栈错误处理程序,ThreadX 将调用内部 tx_thread_stack_error_handler 例程。
(4) 堆栈帧指的是在堆栈中为当前正在运行的函数分配的区域
8.可重入函数
多线程处理可以从多个线程中调用相同的 C 函数,此C 函数是可重入的函数。可重入函数将调用方的返回地址存储在当前堆栈上,并且不依赖于先前设置的全局或静态 C 变量,我们只须关心如何使用全局和静态变量 。
9.线程优先级缺陷
(1) 线程资源不足:优先级较高的线程始终准备就绪,则不会执行优先级较低的线程
解决:逐渐提高资源不足的线程的优先级,直到有机会执行这些线程。
(2) 优先级反转:当一个线程由于等待比它优先级低的线程释放资源而被阻塞
解决:优先级较低的线程可以利用抢占阈值来阻止中等优先级线程在其与优先级较高的线程共享资源时执行抢占;互斥对象保护系统资源的线程可以利用互斥优先级继承。
10.优先级开销
假设有一个包含三个线程的环境,这些线程分别命名为thread_1、thread_2 和 thread_3 。 进一步假定所有线程都处于等待消息的挂起状态。 当 thread_1 收到消息后,立即将其转发给 thread_2。 随后,thread_2 将此消息转发给 thread_3。 Thread_3 只是丢弃此消息。 每个线程处理其消息后,则会返回并等待另一个消息。执行这三个线程所需的处理存在很大的差异,具体取决于其优先级。 如果所有线程都具有相同优先级,则会在执行每个线程之前发生一次上下文切换。 当每个线程在空消息队列中挂起时,将会发生上下文切换。但是,如果 thread_2 的优先级高于 thread_1,thread_3 的优先级高于 thread_2,上下文切换的次数将增加一倍。这是因为当其检测到优先级更高的线程现已准备就绪时,会在 tx_queue_send 服务中执行另一次上下文切换。
11.运行时线程性能信息
可通过tx_thread_performance_info_get 和 tx_thread_performance_system_info_get获得。
(1) 整个系统的总数
线程恢复数、线程挂起数、服务调用抢占次数、中断抢占次数、优先级反转数、时间片数、放弃次数、线程超时数、挂起中止数、空闲系统返回数、非空闲系统返回数
(2) 每个线程的总数
恢复数、挂起数、服务调用抢占次数、中断抢占次数、优先级反转数、时间片数、线程放弃数、线程超时数、挂起中止数
如果服务调用抢占数量相对较多,可能表明线程的优先级和/或抢占阈值过低。 此外,如果空闲系统返回次数相对较少,可能表明优先级较低的线程没有完全挂起。
更多推荐
线程相关的
发布评论