空闲线程是系统线程中一个比较特殊的线程,它具有最低的优先级,当系统中无其他线程可运行时,调度器将调度到空闲线程。空闲线程通常是一个死循环,永远不被挂起。RT-Thread实时操作系统为空闲线程提供了钩子函数(钩子函数:用户提供的一段代码,在系统运行的某一路径上设置一个钩子,当系统经过这个位置时,转而执行这个钩子函数,然后再返回到它的正常路径上),可以让系统在空闲的时候执行一些特定的任,例如系统运行指示灯闪烁,电源管理等。除了调用钩子函数,RT-Thread也把线程清理(rt_thread->cleanup回调函数)函数、真正的线程删除动作放到了空闲线程中(在脱离或删除线程时,仅改变线程的状态为关闭状态不再参与系统调度)。

空闲线程函数接口:(在src/idle.c中定义)

空闲线程初始化:
/**
* @ingroup SystemInit
*
* This function will initialize idle thread, then start it.
*
* @note this function must be invoked when system init.
*/
void rt_thread_idle_init(void)
{
/* initialize thread */
rt_thread_init(&idle,
"tidle",
rt_thread_idle_entry, //空闲线程入口函数
RT_NULL, //入口函数参数为空
&rt_thread_stack[], //空闲线程栈地址
sizeof(rt_thread_stack), //栈大小,默认为128字节,若使用钩子函数或动态堆时为256字节,在idle.c中宏定义
RT_THREAD_PRIORITY_MAX - ,//空闲线程优先级最低
); //时间片为32个时钟节拍 /* startup */
rt_thread_startup(&idle);
}
空闲线程入口函数:
static void rt_thread_idle_entry(void *parameter)
{
while ()
{
#ifdef RT_USING_HOOK
if (rt_thread_idle_hook != RT_NULL)
rt_thread_idle_hook();//若使用钩子且钩子函数不为空,则执行钩子函数
#endif rt_thread_idle_excute(); //空闲线程的真正执行函数
}
}
空闲线程执行函数:
void rt_thread_idle_excute(void)
{
/* Loop until there is no dead thread. So one call to rt_thread_idle_excute
* will do all the cleanups. */
while (_has_defunct_thread()) //检查僵尸线程链表中是否存在僵尸线程,以前的版本中用if (!rt_list_isempty(&rt_thread_defunct))来判断,这样每次只能清除一个僵尸线程
{
rt_base_t lock;
rt_thread_t thread;
#ifdef RT_USING_MODULE
rt_module_t module = RT_NULL;
#endif
RT_DEBUG_NOT_IN_INTERRUPT; //确保此函数不是在中断服务中,若RT_DEBUG_CONTEXT_CHECK is 1 in rtdebug.h,则该宏表示这个函数不能用于中断ISR中。通过检查rt_interrupt_nest中断嵌套计数器是否为0来判断 /* disable interrupt */
lock = rt_hw_interrupt_disable(); /* re-check whether list is empty */
if (_has_defunct_thread()) //再次判断rt_thread_defunct是否为空,若不为空
{
/* get defunct thread */
thread = rt_list_entry(rt_thread_defunct.next,
struct rt_thread,
tlist); //获取待回收的僵尸线程
#ifdef RT_USING_MODULE
/* get thread's parent module */
module = (rt_module_t)thread->module_id;//得到模块ID /* if the thread is module's main thread */
if (module != RT_NULL && module->module_thread == thread)
{
/* detach module's main thread */
module->module_thread = RT_NULL; //清空模块线程
}
#endif
/* remove defunct thread */
rt_list_remove(&(thread->tlist)); //重置线程链表节点为初始值,即节点next与prev均指向自身节点,即将线程从僵尸线程链表中移除
/* invoke thread cleanup */
if (thread->cleanup != RT_NULL)
thread->cleanup(thread); //执行线程清理函数 /* if it's a system object, not delete it */
if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)//若该僵尸线程内核对象为静态对象,则不删除该对程内核对象
{
/* enable interrupt */
rt_hw_interrupt_enable(lock); return;
}
}
else //若再次判断rt_thread_defunct僵尸线程链表为空
{
/* enable interrupt */
rt_hw_interrupt_enable(lock); /* may the defunct thread list is removed by others, just return */
return;
} /* enable interrupt */
rt_hw_interrupt_enable(lock); #ifdef RT_USING_HEAP //程序运行到这,说明上文处理的僵尸线程为动态创建的线程
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
/* the thread belongs to an application module */
if (thread->flags & RT_OBJECT_FLAG_MODULE)
rt_module_free((rt_module_t)thread->module_id, thread->stack_addr);//释放模块主线程栈所占内存
else
#endif
/* release thread's stack */
RT_KERNEL_FREE(thread->stack_addr); //释放动态线程栈所占内存
/* delete thread object */
rt_object_delete((rt_object_t)thread);//删除动态线程内核对象,即从当前类型的内核对象链表中移除,同时释放内核对象所占空间(若使用了模块功能,还要释放模块ID所占空间)
#endif #ifdef RT_USING_MODULE
if (module != RT_NULL)
{
extern rt_err_t rt_module_destroy(rt_module_t module); /* if sub thread list and main thread are all empty */ //若模块主线程为空,且子线程对象链表为空
if ((module->module_thread == RT_NULL) &&
rt_list_isempty(&module->module_object[RT_Object_Class_Thread].object_list))
{
module->nref --;
} /* destroy module */
if (module->nref == )
rt_module_destroy(module);//销毁模块
}
#endif
}
}

由上述代码可知,空闲线程很大一部分的工作就是回收僵尸线程。那么这些线程又是如何而来的呢?

在线程被脱离或删除时,会将线程加入到回收链表rt_thread_defunct中,此链表在scheduler.c源文件中定义,专门用来保存待回收的线程。

最新文章

  1. 虚拟机拷贝后网卡eth0变成了eth1的解决办法
  2. eclipse:不能在tomcat里添加一个项目的解决方法
  3. Android开发自学笔记(Android Studio1.3.1)—2.开始第一个Android应用
  4. mina2
  5. 【HDOJ】1669 Jamie's Contact Groups
  6. oracle 中使用触发器自动生成UUID
  7. CC Arithmetic Progressions (FFT + 分块处理)
  8. java中文乱码解决之道(二)—–字符编码详解:基础知识 + ASCII + GB**
  9. 拿出来分享了!VIP珍藏!!!全网最齐全的 DEDECMS模板 全盘下载地址列表!没有你找不到的!
  10. 安卓组件service
  11. tensorflow l2_normalize函数
  12. 【转载】基于vw等viewport视区相对单位的响应式排版和布局
  13. Xaramin IOS 开发常见问题
  14. MySQL查询性能优化(精)
  15. C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)
  16. Java基础 【Arrays 类的使用】
  17. React Native(十一)——按钮重复点击事件的处理
  18. 使用C#中的out关键字,用世界杯演绎
  19. HIVE HBASE 整合
  20. 控制input框的内容输入为数字

热门文章

  1. BZOJ1303_中位数图_KEY
  2. 成都Uber优步司机奖励政策(1月9日)
  3. 武汉Uber优步司机奖励政策(12月14日到12月20日)
  4. P2351 [SDOi2012]吊灯
  5. 一、Lambda表达式
  6. 在Win10中通过命令行打开UWP应用
  7. 05-JVM对象探秘
  8. linux-centos6②
  9. 对JSON的理解
  10. Appium安装教程