RT-Thread线程的使用

1、动态创建和静态创建线程区别说明
RT-Thread创建线程分为两种方式,一种是动态创建线程,一种静态创建线程,在不加外部RAM的情况下,两种创建方式效率相同,如果加了外部RAM,则静态创建线程效率高一些。
为什么创建静态线程不用外部RAM而创建动态线程用外部RAM?当用户将变量定义到文件或函数内部而不指定地址时,默认使用内部RAM,而创建静态线程将栈空间的大小提前在文件或函数中定义好的,所以不用外部RAM。

2、线程优先级和时间片说明
1)线程优先级
优先级和时间片是线程的两个重要参数,分别描述了线程竞争处理器资源的能力和持有处理器时间长短的能力。
RT-Thread最大支持256个优先级,数字越低代表优先级越高,数字越高则优先级越低。如0优先级最高,255优先级最低,优先级会发生抢占调度,当新创建的线程属于最高优先级并处于就绪态时,肯定会进行任务调度,有效的保证了优先级的抢占机制。
可以通过rt_config.h的RT_THREAD_PRIORITY_MAX宏修改最大支持的优先级;针对STM32系列默认支持32个优先级。
官方文档描述说线程数是不受限制的,线程总数应该只和具体的硬件平台的内存有关。
2)时间片
时间片是用来约束相同优先级线程的机制,单位是系统节拍OS Tick。对不同优先级线程起到的作用有限。
运行机制是假设当前有A、B两个相同优先级的线程,A是时间片是10,B的时间片是5,并且当前并没有比A、B优先级更高的线程在运行,那么系统的运行机制是先在A线程运行10个OS Tick,而后B线程运行5个OS Tick,B线程运行完后再运行A线程,如此循环往复,直到线程被打断。

3、空闲线程
空闲线程是系统当前无可运行线程后才会运行的一种线程,他的优先级最低,且永远不会被挂起。主要负责将关闭态的线程从调度列表中删除的操作,并向用户提供了钩子函数,在无线程运行时会执行一些系统运行指示灯、CPU使用率等功能。
空闲线程是一个线程状态永远为就绪态的线程,如果加钩子函数需要注意不能添加系统延时函数,必须保证空闲线程在任何时刻都不会被挂起,例如rt_thread_delay()、rt_sem_take()。可能导致线程挂起的阻塞类函数都不能在钩子函数中使用。
这里延伸两个知识点
1)钩子函数不能调用系统API,也不能被挂起,那么钩子函数能用来做什么?
首先钩子函数分为两种,一种是空闲线程下的钩子函数:
rt_err_t rt_thread_idle_sethook(void (*hook)(void))
rt_err_t rt_thread_idle_delhook(void (hook)(void))
和系统调用钩子函数(只有设置没有删除):
rt_scheduler_sethook(void (hook)(struct rt_thread from, struct rt_thread to))
并且在钩子函数使用前需要注意rtconfig.h下的宏RT_USING_HOOK是否定义,而且空闲线程下的钩子函数最多设置四个,系统调用函数钩子函数最多设置一个,空闲线程下的钩子函数主要作用是用来处理不能延时类的操作,例如标志位、或者莫个GPIO口的高低电平。而系统调用钩子函数主要作用是用来告诉开发者当前系统调用信息。
2)钩子函数为什么不能调用系统API?为什么不能被挂起?
举个例子:空闲线程中包含自动删除结束态的线程,主要用来回收系统资源,如果该线程不小心挂起,会造成系统资源的过度累积,导致系统崩溃。为什么不能调用系统API这个问题就抛出来吧,我也没搞太懂,哪位路过的大侠指点一下。
4、函数说明
静态线程函数
rt_err_t rt_thread_init(struct rt_thread
thread, const char
name, void (entry)(void parameter), void
parameter, void
stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick);
函数描述:函数主要创建一个静态线程函数任务,函数线程块,栈空间都定义在全局变量,在编译时就被确定、被分配处理,内核不负责线程块的创建及内存分配。需要注意的是,用户提供的栈首地址需要做字节对齐,例(ARM4字节对齐),线程安全,并且可以调用中断例程。
参数 描述
thread 线程句柄。线程句柄由用户提供出来,并指向对应的线程控制块 内存地址。
name 线程的名称;线程名称的最大长度由rtconfig.h中定义的 RT_NAME_MAX宏指定,多余部分会被自动截掉。
entry 线程入口函数
parameter 线程入口函数参数;
stack_start 线程栈起始地址;
stack_size 线程栈大小,单位是字节。在大多数系统中需要做栈空间地址对 齐(例如ARM体系结构中需要向4字节地址对齐)。
priority 线程的优先级。优先级范围根据系统配置情况(rtconfig.h中的 RT_THREAD_PRIORITY_MAX宏定义),如果支持的是256级优先 级,那么范围是从0 ~ 255,数值越小优先级越高,0代表最高优 先级。
tick 线程的时间片大小。时间片(tick)的单位是操作系统的时钟节 拍。当系统中存在相同优先级线程时,这个参数指定线程一次调 度能够运行的最大时间长度。这个时间片运行结束时,调度器自 动选择下一个就绪态的同优先级线程进行运行。
返回值:线程创建结果,成功返回RT_EOK.

动态线程函数
rt_thread_t rt_thread_create(const char* name, void (entry)(void parameter), void* parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick);
函数说明:系统会从动态堆内存中分配一个线程句柄(即TCB,线程控制块) 以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照 rtconfig.h中配置的RT_ALIGN_SIZE方式对齐。线程安全,不能调用中断例程。
参数 描述
name 线程的名称,线程名称的最大长度由rtconfig.h中定义的 RT_NAME_MAX宏指定,多余部分会被自动截掉。
entry 线程入口函数
parameter 线程入口函数参数
stack_size 线程栈大小,单位是字节。在大多数系统中需要做栈空间地址对 齐(例如ARM体系结构中需要向4字节地址对齐)。
priority 线程优先级,优先级范围根据系统配置情况(rtconfig.h中的 RT_THREAD_PRIORITY_MAX宏定义),如果支持的是256级优先 级,那么范围是从0 ~ 255,数值越小优先级越高,0代表最高优先级。
tick 线程的时间片大小。时间片(tick)的单位是操作系统的时钟节 拍。当系统中存在相同优先级线程时,这个参数指定线程一次调 度能够运行的最大时间长度。这个时间片运行结束时,调度器自 动选择下一个就绪态的同优先级线程进行运行。
返回值:创建成功返回线程句柄,创建失败返回RT_NULL。

线程启动函数
rt_err_t rt_thread_startup(rt_thread_t thread)
函数描述:当调用这个函数时,将把线程的状态改为就绪态,并放到相应的优先级队列中,如果新启动的线程优先级比正在运行的优先级高,那么将先优先执行新启动的线程。函数安全,可以执行中断例程。
参数 描述
thread 线程句柄
返回值 RT_EOK。

猜你喜欢

转载自blog.csdn.net/weixin_42560250/article/details/105491618