对空闲线程的理解
空闲线程对于一个实时操作系统来说是十分重要的。因为线程会因为需要而主动放弃对CPU的使用,而恰好当前所有线程都放弃对CPU的使用,这时候就需要一个保底的线程----优先级最低的空闲线程。
空闲线程的实现
空闲线程也是一个线程,同样是调用rt_thread_init函数创建的。
static struct rt_thread idle;
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_thread_stack[IDLE_THREAD_STACK_SIZE];
static void rt_thread_idle_entry(void *parameter)
{
#ifdef RT_USING_IDLE_HOOK
rt_size_t i;
#endif
while (1)
{
#ifdef RT_USING_IDLE_HOOK
for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
{
if (idle_hook_list[i] != RT_NULL)
{
idle_hook_list[i]();
}
}
#endif
rt_thread_idle_excute();
}
}
/**
* @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),
RT_THREAD_PRIORITY_MAX - 1,
32);
/* startup */
rt_thread_startup(&idle);
}
这里还牵扯到钩子函数,嗯~我以后有机会也会详细对这一部分说一下我的理解的。
对阻塞延时的理解
阻塞延时,他和我们之前使用的延时的区别就是:
1.阻塞延时是放弃CPU的控制,而之前的延时方式是强制CPU不做有效的操作而实现延时。
2.很明显阻塞延时需要统计阻塞时间。
阻塞延时的实现
1.需要挂起当前函数。
2.需要计算恢复就绪态的时间。
3.线程的切换。
支持修改当前线程的状态
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 */
...
...
rt_uint8_t stat; /**< thread status */
...
...
};
/*
* thread state definitions
*/
#define RT_THREAD_INIT 0x00 /**< Initialized status */
#define RT_THREAD_READY 0x01 /**< Ready status */
#define RT_THREAD_SUSPEND 0x02 /**< Suspend status */
#define RT_THREAD_RUNNING 0x03 /**< Running status */
#define RT_THREAD_BLOCK RT_THREAD_SUSPEND /**< Blocked status */
#define RT_THREAD_CLOSE 0x04 /**< Closed status */
#define RT_THREAD_STAT_MASK 0x0f
线程有可以记录自己的状态statu的时候,才是可以区别自己状态的时间。
如你看到的,挂起态和阻塞态其实是同一种状态
我们通过修改thread->stat = RT_THREAD_INIT;这样的语句来改变线程的状态,
支持记录线程恢复就绪态时间统计
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 */
...
...
rt_ubase_t remaining_tick; /**< remaining tick */
...
...
};
通过修改每个线程控制块内的remaining_tick,可以将线程需要延时的时间和系统的滴答时钟联系起来,所以,我们在视频中会听到关于系统的最小的运行时间单位这样的表述。
支持线程的切换
这时系统还不支持多优先级,但是我们已经了解过关于线程切换的相关知识了。我们是可以使系统可以进行线程切换的,大概示意如下:
接下来就是优先级了,优先级需要考虑的重要问题:
- 调度程序是怎么在一堆线程中找到最需要执行的线程?
- 编程时候怎么注意什么,可以尽可能避免BUG?