1、RTOS
RTOS代表实时操作系统(Real-Time Operating System)。
一种专为实时应用程序设计的操作系统,用于控制嵌入式系统中的实时任务和事件。
RTOS的主要特点是能够满足严格的时间约束和响应要求。
2、线程
在RTOS中,线程(Thread)是一种表示任务执行的基本单位。
RTOS中的线程类似于通用操作系统中的线程概念,
在RTOS中,线程通常具有更严格的时间约束和实时性要求。
系统中有两种线程:
- 系统线程:RT内核创建
- 用户线程:用户应用程序创建
3、线程间切换的时候需要做什么工作
1、保存当前线程上下文
2、选择下一个线程
3、恢复下一个线程的上下文
4、切换堆栈和地址空间
5、更新调度器状态
6、执行下一个线程
4、什么叫保存线程
把暂停瞬间CPU内的值保存进栈里
5、保存线程需要保存哪些寄存器的哪些值?
4、如何创建线程
RT-Thread中创建线程的两种方式
静态创建线程:rt_thread_init();
动态创建线程:rt_thread_startup();
//静态创建线程
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); //线程时间片大小
//动态创建线程
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); //线程时间片大小
静态创建和动态创建的区别:
1、栈空间区别:
动态线程:是系统自动从动态内存堆上分配栈空间与线程句柄
静态线程:是由用户分配栈空间与线程句柄
2、参数区别:
静态创建线程:输入需要线程的句柄(线程控制块),返回值是RT_EOK / RT_ERROR
动态创建线程:返回值是线程的句柄(线程控制块),需要用启动线程函数启动
启动线程函数:rt_err_t rt_thread_startup ( rt_thread_t thread );输入创建的线程句柄返回值: RT_EOK ; RT_ERROR
创建线程中重点需要两个东西
1、线程函数:也就是入口函数
2、线程的栈:也就是线程栈
线程的组成:
1、线程控制块:
由结构体 struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构。
它存放线程的一些信息:
- RT对象:线程名字、对象类型、标注位、对象列表、线程列表
- 栈指针和入口指针:栈指针、入口函数指针、参数、栈指针地址、栈大小
- 错误代码:线程错误代码、线程状态
- 优先级:当前优先级、初始优先级
- 其他:线程初始化数值、线程剩余计数值、内置线程定时器、线程退出清理函数、用户私有数据
-
/** * Thread structure */ struct rt_thread { /* rt 对象 */ char name[RT_NAME_MAX]; /* 线程名字 */ rt_uint8_t type; /* 对象类型 */ rt_uint8_t flags; /* 标注位 */ rt_list_t list; /* 对象列表 */ rt_list_t tlist; /* 线程列表 */ /* 栈指针和入口指针 */ void *sp; /* 栈指针 */ void *entry; /* 入口函数指针*/ void *parameter; /* 参数 */ void *stack_addr; /* 栈地址指针 */ rt_uint32_t stack_size; /* 栈大小*/ /* 错误代码 */ rt_err_t error; /* 线程错误代码 */ rt_uint8_t stat; /* 线程状态 */ /* 优先级 */ rt_uint8_t current_priority; /* 当前优先级 */ rt_uint8_t init_priority; /* 初始优先级 */ ………… rt_ubase_t init_tick; /* 线程初始化计数值 */ rt_ubase_t remaining_tick; /* 线程剩余计数值 */ struct rt_timer thread_timer; /* 内置线程定时器 */ void (*cleanup)(struct rt_thread *tid); /* 线程退出清理函数 */ rt_uint32_t user_data; /* 用户私有数据*/ }; typedef struct rt_thread *rt_thread_t;
2、线程栈:
可以使用两种方法提供线程栈:静态分配、动态分配
栈的大小通常由用户定义
rt_uint32_t test_stack[512];
也可以在初始化时设置为较大的栈,比如
1K
或
2K
,
在进入系统后,通过终端的
list_thread
命令查看当前线程栈的最大使用率。
如果使用率超过
70%
,将线程栈再设置大
一点;
如果远低于
70%
,将线程栈设置小一点。
3、入口函数:
入口函数是线程要运行函数,由用户自行设计。
可分为无限循环模式和顺序执行模式。
无限循环:
void thread_entry(void* paramenter)
{
while (1)
{
/* 等待事件的发生 */
/* 对事件进行服务、进行处理 */
}
}
在这种模式中,需要调用延时函数或者主动挂起。
顺序执行:
static void thread_entry(void* parameter)
{
/* 处理事务 #1 */
…
/* 处理事务 #2 */
…
/* 处理事务 #3 */
}
执行完毕后,线程将被系统自动删除。
5、删除线程:
两种创建线程的方式对应不同的删除方式
// 删除使用 rt_thread_init()创建的线程
rt_err_t rt_thread_detach (rt_thread_t thread);
// 删除使用 rt_thread_create()创建的线程
rt_err_t rt_thread_delete (rt_thread_t thread);
- rt_thread_delete 并不是真正的删除线程,只是把线程状态状态改为 RT_THREAD_CLOSE。
- 真正的删除(释放线程控制块和线程栈),在下一次执行空闲线程时,由空闲线程删除
- 线程本身不应调用 rt_thread_detach 脱离线程