线程的五种状态:
**
RT-Thread 最大支持 256 个线程优先级 (0~255),数值越小的优先级越高,0 为最高优先级。
注意:当有比当前线程优先级更高的线程就绪时,当前线程才将立刻被换出,高优先级线程抢占处理器运行。
时间片仅对优先级相同的就绪态线程有效。
线程中不能陷入死循环操作,必须要有让出 CPU 使用权的动作,如**循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。**
main 线程的入口函数为 main_thread_entry()
用户可以在 main() 函数里添加自己的应用程序初始化代码。
创建一个线程 接口如下:
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);
rt_err_t rt_thread_init(struct rt_thread* 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_err_t rt_thread_startup(rt_thread_t thread);
获取当前线程:
在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:
rt_thread_t **rt**_thread_self(void);
使线程睡眠:
在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做 “线程睡眠”。线程睡眠可使用以下三个函数接口:
rt_err_t ** rt_thread_sleep(rt_tick_t tick);
rt_err_t **rt_thread_delay(rt_tick_t tick);
rt_err_t ** rt_thread_mdelay(rt_int32_t ms);**
使线程让出处理器:
当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。
rt_err_t ** rt_thread_yield(void);
(调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换)
当线程调用 rt_thread_delay() 时,线程将主动挂起;当调用 rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。
线程恢复:
rt_err_t rt_thread_resume (rt_thread_t thread);
控制线程:
当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:
rt_err_t **rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void arg);*
指示控制命令 cmd 当前支持的命令包括:
•RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级;
•RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于 rt_thread_startup() 函数调用;
•RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于 rt_thread_delete() 函数调用。
空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如 rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。