RTT学习笔记之线程调度与管理

来源:互联网 发布:淘宝新卖家如何推广 编辑:程序博客网 时间:2024/06/15 16:32
RTT学习笔记之线程调度与管理

     一个简单的程序会设计成一个串行的系统运行:按照准确的指令步骤一次一个指令的运行。但是这种方法对与复杂一些的实时应用是不可行的,因为它们通常需要在固定的时间内“同时”处理多个输入输出,实时软件应用程序应该设计成一个并行的系统,并行系统的设计就需要开发人员将应用划分成一个个小的、可调度的、序列化的单元,当合理的划分任务,正确的并行执行时,这种设计能够让系统满足实时系统的性能及时间的要求。

1、实时系统的需求
     实时系统指的是在固定的时间内(deadline)正确的对外部事件做出响应。而在这段时间内系统可能会闲下来处理其他的事情。实时系统是一个需求倾向型的系统,通过优先级的方式,来保证重要的任务得到优先处理,这就需要任务是可以被抢占的,所以实时系统也可以看成是一个等级系统,在RTT中任务采用线程来实现,线程是最基本的调度单位,它描述了一个任务执行的上下文的关系,也描述了任务所处的优先级。重要的任务拥有较高的优先级,非重要的任务拥有相对较低的优先级,同样支持几个任务拥有相同的优先级,这样的任务采用时间片的方式进行任务切换。

2、线程调度器
     RTT中提供的线程调度器是基于全抢占式优先级的调度,系统中除了中断处理函数、调度器上锁、禁止中断部分代码是不可抢占之外,系统的其他部分都是可以抢占的,包括线程调度器自身,系统一共支持256个优先级(0-255,数字越小,优先级越高),RTT调度器的实现中包含了一组拥有256个优先级的队列数组,每个优先级队列采用双向环形链表的方式链接。rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
由于在任务切换时,查找优先级较高的任务所花费的时间将大大影响系统的实时性,调度器在查找高优先级任务进行切换时是采用位图的方式进行查找,具体实现代码如下所示:
#if RT_THREAD_PRIORITY_MAX > 32    register rt_ubase_t number;    number = __rt_ffs(rt_thread_ready_priority_group) - 1;    highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;#else    highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;int __rt_ffs(int value){    if (value == 0) return 0;    if (value & 0xff)        return __lowest_bit_bitmap[value & 0xff] + 1;    if (value & 0xff00)        return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;    if (value & 0xff0000)        return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;    return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;}
3、线程控制块
/*** Thread structure*/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_uint16_t stack_size;                             /**< stack size */    /* error code */    rt_err_t    error;                                  /**< error code */    rt_uint8_t  stat;                                   /**< thread stat */    /* 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    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 */    rt_uint32_t user_data;                              /**< private user data beyond this thread */};typedef struct rt_thread *rt_thread_t;
4、线程状态
线程有以下几种状态,其中BLOCK和SUSPEND状态相同,为阻塞/挂起状态,暂时交出CPU的控制权。
/** 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 */
5、调度器的相关接口
调度器初始化:
void rt_system_scheduler_init(void)
启动调度器:
void rt_system_scheduler_start(void)
执行调度器(一次):
void rt_schedule(void)
6、线程相关接口
动态创建线程:
rt_thread_t rt_thread_create(const char *name,                             void (*entry)(void *parameter),                             void       *parameter,                             rt_uint32_t stack_size,                             rt_uint8_t  priority,                             rt_uint32_t tick)
参数分别为:线程名称、入口位置、入口参数、栈大小、优先级、时间片
Note: 确定一个线程的栈空间大小,是一件令人繁琐的事情,在RT-Thread中,可以先指定一个稍微大的栈空间,例如1024或2048,然后在FinSH shell中查看线程运行的过程中线程使用栈的最大值(在RT-Thread中,会记录一个线程使用过程中使用到的栈的最大深度,通过finsh shell命令list thread()可以看到从系统启动时,到当前时间点,线程使用的最大栈深度)。调用这个函数后,系统会从动态堆内存中分配一个线程句柄(即TCB,线程控制块)以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。

线程删除:
rt_err_t rt_thread_delete(rt_thread_t thread){    rt_base_t lock;    /* thread check */    RT_ASSERT(thread != RT_NULL);    /* 从调度器链表中移除 */    rt_schedule_remove_thread(thread);    /* 释放定时时间并删除内核对象 */    rt_timer_detach(&(thread->thread_timer));    /* 改变相称状态 */    thread->stat = RT_THREAD_CLOSE;    /* disable interrupt */    lock = rt_hw_interrupt_disable();    /* 插入到销毁线程链表 */    rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));    /* enable interrupt */    rt_hw_interrupt_enable(lock);    return RT_EOK;}
线程初始化:
rt_err_t rt_thread_init(struct rt_thread *thread,                        const char       *name,                        void (*entry)(void *parameter),                        void             *parameter,                        void             *stack_start,                        rt_uint32_t       stack_size,                        rt_uint8_t        priority,                        rt_uint32_t       tick)
线程脱离:
rt_err_t rt_thread_detach(rt_thread_t thread)
线程启动:
rt_err_t rt_thread_startup(rt_thread_t thread)
线程让出处理机:
rt_err_t rt_thread_yield(void)
线程睡眠:
rt_err_t rt_thread_sleep(rt_tick_t tick)
线程挂起:
rt_err_t rt_thread_suspend(rt_thread_t thread)
线程延时:
rt_err_t rt_thread_delay(rt_tick_t tick)
线程控制:
rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void *arg)
线程恢复:
void rt_thread_timeout(void *parameter)
7、简单例程
#include <board.h>#include <rtthread.h>#include "led.h"ALIGN(RT_ALIGN_SIZE)static rt_uint8_t led_stack[ 512 ];// 线程栈空间static struct rt_thread led_thread;// 线程名称static void led_thread_entry(void* parameter){    rt_hw_led_init();// 硬件初始化    while (1)    {        rt_hw_led_on(0);// 打开led        rt_thread_delay( RT_TICK_PER_SECOND/2 );// Sleep 0.5秒,交出CPU控制权.        rt_hw_led_off(0);// 关闭led        rt_thread_delay( RT_TICK_PER_SECOND/2 );// Sleep 0.5秒,交出CPU控制权.    }}int rt_application_init(void){    rt_err_t result;    // 创建led_thread线程,入口函数为led_thread_entry,入口函数参数为RT_NULL,栈起始地址:led_stack[0],栈大小:0x200,优先级:20,时间片:5tick。     result = rt_thread_init(&led_thread,                            "led",                            led_thread_entry,                            RT_NULL,                            (rt_uint8_t*)&led_stack[0],                            sizeof(led_stack),                            20,                            5);    if (result == RT_EOK)    {        rt_thread_startup(&led_thread);// 启动led_thread线程    }    return 0;}
静态创建一个led呼吸灯线程,线程栈空间为0x200,实现0.5秒的呼吸灯操作。

0 0
原创粉丝点击