RT-thread内核之空闲线程

来源:互联网 发布:霸王举鼎是真的吗 知乎 编辑:程序博客网 时间:2024/05/16 06:56

空闲线程是系统线程中一个比较特殊的线程,它具有最低的优先级,当系统中无其他线程可运行时,调度器将调度到空闲线程。空闲线程通常是一个死循环,永远不被挂起。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[0],       //空闲线程栈地址                   sizeof(rt_thread_stack),   //栈大小,默认为128字节,若使用钩子函数或动态堆时为256字节,在idle.c中宏定义                   RT_THREAD_PRIORITY_MAX - 1,//空闲线程优先级最低                   32);                       //时间片为32个时钟节拍    /* startup */    rt_thread_startup(&idle);}
复制代码
复制代码
空闲线程入口函数:static void rt_thread_idle_entry(void *parameter){    while (1)    {        #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 == 0)                rt_module_destroy(module);//销毁模块          }#endif    }}
复制代码

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

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

0 0
原创粉丝点击