RT-Thread是支持多任务的操作系统,多任务通过多线程的方式实现。线程是任务的载体,也是RTT中最基本的调度单位。
线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。
特点
RTT系统中总共存在两类线程,分别是系统线程和用户线程,系统线程由内核创建,用户线程由应用程序创建,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会从对象容器中删除。
RTT的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU的使用权。
当调度器调度线程切换时,先将当前线程上下文保存起来,再切回到这个线程时,将该线程的上下文恢复。
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 */
#ifdef RT_USING_MODULE
void *module_id; /**< id of application module */
#endif
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 */
rt_uint32_t stack_size; /**< stack size */
/* error code */
rt_err_t error; /**< error code */
rt_uint8_t stat; /**< thread status */
#ifdef RT_USING_SMP
rt_uint8_t bind_cpu; /**< thread is bind to cpu */
rt_uint8_t oncpu; /**< process on cpu` */
rt_uint16_t scheduler_lock_nest; /**< scheduler lock count */
rt_uint16_t cpus_lock_nest; /**< cpus lock count */
rt_uint16_t critical_lock_nest; /**< critical lock count */
#endif /*RT_USING_SMP*/
/* priority */
rt_uint8_t current_priority; /**< current priority */
rt_uint8_t init_priority; /**< initialized priority */
#if RT_THREAD_PRIORITY_MAX > 32
rt_uint8_t number;
rt_uint8_t high_mask;
#endif
rt_uint32_t number_mask;
#if defined(RT_USING_EVENT)
/* thread event */
rt_uint32_t event_set;
rt_uint8_t event_info;
#endif
#if defined(RT_USING_SIGNALS)
rt_sigset_t sig_pending; /**< the pending signals */
rt_sigset_t sig_mask; /**< the mask bits of signal */
#ifndef RT_USING_SMP //对称多处理器,Cortex-M3是单核的
void *sig_ret; /**< the return stack pointer from signal */
#endif
rt_sighandler_t *sig_vectors; /**< vectors of signal handler */
void *si_list; /**< the signal infor list */
#endif
rt_ubase_t init_tick; /**< thread's initialized tick */
rt_ubase_t remaining_tick; /**< remaining tick */
struct rt_timer thread_timer; /**< built-in thread timer */
void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */
/* light weight process if present */
#ifdef RT_USING_LWP
void *lwp;
#endif
线程与线程之间用链接结构进行连接。
cleanup函数指针指向的函数,会在线程退出的时候,被idle线程回调一次,执行用户设置的清理现场等工作。
线程属性
线程栈
每个RT-Thread线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。
线程状态
stat
- 初始状态:当线程刚开始创建还没开始运行时就处于就绪状态;在初始状态下,线程不参与调度,定义为RT_THREAD_INIT。
- 就绪状态:在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行,定义为RT_THREAD_READY。
- 运行状态:线程当前正在运行。在单核系统中,只有rt_thread_self()函数返回的线程处于运行状态。多核系统中,可能就不止一个。定义为RT_THREAD_RUNNING。
- 挂起状态:也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。RT_THREAD_SUSPEND。
- 关闭状态:当线程运行结束时处于关闭状态。关闭状态的线程不参与线程的调度。RT_THREAD_CLOSE。
线程优先级
RTT最大支持256个优先级(0~255),数值越小的优先级越高,0为最高优先级。
在一些资源比较紧张的系统中,可以根据实际情况选择只支持8个或32个优先级的系统配置。
对于ARM Cortex-M系列,普遍采用32个优先级。
最低优先级默认分配给空闲线程使用,用户一般不使用。
在系统中,当有比当前线程优先级更高的线程就绪时,当前线程立刻被换出,高优先级线程抢占处理器运行。
时间片
每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。
注意
作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级的线程都将不能够得到执行。
因此,线程中不能陷入死循环操作,必须要有让出CPU使用权的操作,如循环中调用延时函数或者主动挂起。