为什么要线程管理 在RTT中,线程是竞争系统运行资源的最小运行单位,而且RTT是一个支持多线程的操作系统,所以就会有各种线程要占用CPU的资源。由于线程都是独立的,每个线程都有单独的堆栈空间、运行状态… 所以,在线程进行切换的时候就很有必要保存每个线程的相关信息,即线程切换时的上下文环境(寄存器值、堆栈内容),这也是调度器的主要职责,当线程再次运行的时候,就可以从堆栈中找到上次运行的环境,从而恢复运行环境。 了解线程管理的必要性后还要知道RTT中的调度方式: 抢占式调度 支持时间片轮转调度 也就是不同优先级之间支持抢占式调度,同一优先级间采用时间片轮转机制。 线程的五种状态 RTT中,线程有五种状态: 初始态:线程创建之初就是初始态,此时还不能被调度 就绪态:此时线程在就绪列表中,可以被调度 运行态:此时线程正在执行,占用CPU 挂起态:线程不在就绪列表,但也没有被删除,处于等待状态 关闭态:此时线程运行结束,等待系统回收资源 总之RTT的线程就是在这五种状态之间转换,转换规则如图: 1.以就绪态为中心,就绪态可以在挂起态和运行态之间切换; 2.运行态可以直接变为挂起态,但挂起态必须经过就绪态才能转换为运行态; 3.只有运行态或者挂起态才可以直接关闭; 4.线程只有在创建之初才是初始态,通过rt_thread_startup()函数来进入就绪态。 线程挂起函数rt_thread_suspend() 可以用rt_thread_suspend()函数来实现对指定线程的挂起,当然,rt_thread_delay()函数也可以实现线程的挂起,rt_thread_delay()使线程进入阻塞,效果和挂起一样。这里主要熟悉一下rt_thread_suspend()函数,下面是RTT官方源代码: /** * This function will suspend the specified thread. * * @param thread the thread to be suspended * * @Return the operation status, RT_EOK on OK, -RT_ERROR on error * * @NOTE if suspend self thread, after this function call, the * rt_schedule() must be invoked. */ rt_err_t rt_thread_suspend(rt_thread_t thread) { register rt_base_t temp; /* 检查线程的状态 */ /* thread check */ RT_ASSERT(thread != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s
", thread->name)); if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY) { RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x
", thread->stat)); return -RT_ERROR; } /* 关闭中断 */ /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* 改变线程的状态为挂起态 */ /* change thread stat */ thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK); rt_schedule_remove_thread(thread); /* 停止线程计时器 */ /* stop thread timer anyway */ rt_timer_stop(&(thread->thread_timer)); /* 打开中断 */ /* enable interrupt */ rt_hw_interrupt_enable(temp); RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread)); return RT_EOK; } 很简单,使用时只需要把线程控制块指针传入形参即可,返回值会反馈挂起成功与否。 线程恢复函数rt_thread_resume() 既然有挂起,就会有恢复。线程恢复函数rt_thread_resume()可以将线程从挂起态之间转换为就绪态(如果该线程优先级为最高,之间转到运行态),看一下RTT官方的源代码: /** * This function will resume a thread and put it to system ready queue. * * @param thread the thread to be resumed * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_resume(rt_thread_t thread) { register rt_base_t temp; /* 检查状态 */ /* thread check */ RT_ASSERT(thread != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s
", thread->name)); if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND) { RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d
", thread->stat)); return -RT_ERROR; } /* 关闭中断 */ /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* 将线程从挂起队列移除 */ /* remove from suspend list */ rt_list_remove(&(thread->tlist)); rt_timer_stop(&thread->thread_timer); /* 打开中断 */ /* enable interrupt */ rt_hw_interrupt_enable(temp); /* 将线程插入到就绪队列 */ /* insert to schedule ready list */ rt_schedule_insert_thread(thread); RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread)); return RT_EOK; } 用法与挂起函数类似,只要传入指定线程的线程控制块即可,返回值会反馈恢复的结果。
原作者:Aspirant-GQ
|