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
- RTT学习笔记之线程调度与管理
- RTT学习笔记之定时器
- RTT学习笔记之信号量
- RTT学习笔记之事件
- RTT学习笔记之内存管理(动态内存)
- rtems线程管理与调度
- 学习笔记之线程调度、优先级和关联性
- RxJava学习笔记之线程调度器Scheduler(二)
- rtems线程管理与调度(一)
- RT-Thread 01线程调度与管理
- [RTT例程练习] 1.5 优先级相同线程轮转调度
- rtt学习笔记一:rtt的软件结构
- Linux设计与实现学习笔记之进程调度
- RTT学习笔记之内存池管理(静态内存池)
- rtt学习笔记二:I/O设备管理
- RTT学习笔记之内核对象模型
- Java线程学习笔记之线程安全与不安全
- 【Java学习笔记】12:线程的状态转换2与优先级调度
- 【转】[译] 深入理解 Promise 五部曲:1. 异步问题
- Java压缩技术
- 为Tomcat指定jdk
- 解决方案、项目、程序集、命名空间区别
- vim常用插件安装
- RTT学习笔记之线程调度与管理
- Android GridLayout简介,以计算器为例
- Visual Studio 2012 使用免费的Team Foundation Service
- Ogre代码学习之1——Ogre中地形lod的基础:deltaHeight的计算
- 关于facebook分享的经验
- 第2章 Java基础
- 统计 访问量前10的ip 及访问次数
- 在无线互联学习的这段时间
- 分享一个链接——MATLAB实现Viterbi译码器