线程的概念
RT-Thread 名为实时线程RTOS
在设计一个较为复杂的应用程序时,通常将一个大型任务分解成多个小任务,然后通过运行这些小任务,最终达到完成大任务的目的
在RT-Thread 中,与上述小任务对应的程序实体就叫做“线程”(或任务),RT-Thread 就是一个能对这些小“线程”进行管理和调度的多“线程”操作系统
线程是实现任务的载体,它是RT-Thread 中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级
线程的组成
RT-Thread 中,线程由三部分组成:
- 线程代码(入口函数)
- 线程控制块
- 线程堆栈
线程代码
无限循环结构
void thread_entry(void *parameter)
{
while(1)
{
/* 等待事件发生 */
/* 处理事件 */
}
}
顺序执行结构
void thread_entry(void *parameter)
{
/* 事务1处理 */
/* 事务2处理 */
.
.
.
/* 事务N处理 */
}
线程控制块
线程控制块是操作系统用于管理线程的一个数据结构,它会记录线程的一些信息,例如优先级、线程名称、线程状态等,也包括线程与线程之间连接用的链表结构,线程等待事件集合等。
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 */
rt_list_t list; /**< the object list */
rt_list_t tlist; /**< the thread list */
/* stack point and entry */
void *sp; /**< stack point */
void *entry; /**< entry */
void *parameter; /**< parameter */
void *stack_addr; /**< stack address */
......
......
}
/* 定义线程控制块的指针*tr_thread_t */
/* tr_thread_t 是指向rt_thread 结构体的指针 */
struct rt_thread *tr_thread_t
定义了线程控制块的指针之后就可以通过之前动态内存分配的方式动态分配一个线程控制块
线程栈
RT-Thread 每个线程都具有独立的栈空间,当进行线程切换时,系统会将当前线程的上下文保存在线程栈当中,当线程要恢复运行时,再从线程栈中读取上下文信息,恢复线程的运行。
线程上下文是指线程执行时的环境,具体来说就是各个变量和数据,包括所有寄存器变量、堆栈信息、内存信息等。
线程栈在形式上是一段连续的内存空间,我们可以通过定义一个数组(静态线程)或者申请一段动态内存(动态线程)来作为线程的栈。
创建线程
创建静态线程
所谓静态,即需要事先定义好线程控制块和栈空间,都是需要静态定义的。
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)
参数说明:
参数 | 含义 |
---|---|
*thread | 线程控制块的地址(需要事先定义一个线程控制块) |
*name | 线程名称 |
(*entry)(void *parameter) | 函数指针,指向线程的入口代码,也就是线程代码 |
*parameter | 向线程代码中传入的参数 |
*stack_start | 线程的栈空间的起始地址 |
stack_size | 线程栈的大小 |
priority | 线程的优先级(数值越小,优先级越高) |
tick | 线程的时间片参数 |
创建动态线程
所谓动态,即线程栈和线程控制块都是自动分配的
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)
参数说明:
参数 | 含义 |
---|---|
*name | 线程名称 |
(*entry)(void *parameter) | 函数指针,指向线程的入口代码,也就是线程代码 |
*parameter | 向线程代码中传入的参数 |
stack_size | 线程栈的大小 |
priority | 线程的优先级(数值越小,优先级越高) |
tick | 线程的时间片参数 |
创建动态线程既不需要输入线程地址,也不需要定义线程控制块,只需要指出线程栈大小
线程控制块的指针作为其返回形式,也就是说,线程控制块和堆栈是函数自动分配的
若线程创建成功,返回非零,否则返回0
启动线程
rt_err_t rt_thread_startup(rt_thread_t thread)
该函数参数为线程控制块的指针
调用此函数后创建的线程会被加入到线程的就绪队列,执行调度
静态线程和动态线程的区别
相关资源分配形式
静态线程的线程控制块和线程栈都需要提前以静态形式定义出来,动态线程则是在运行过程中动态分配。
运行效率
若静态线程和动态线程的线程控制块及线程栈都处于芯片内部RAM 中,则二者的运行效率差别不大。
但若系统使用了外扩RAM,动态线程的线程控制块和线程栈从外扩RAM 中分配的话,其运行效率会下降。
我觉得嵌入式系统对于线程的实现,应该就是基于单片机的嵌套中断吧