RT-thread内核之线程调度器

http://www.cnblogs.com/King-Gentleman/p/4278012.html

一、前言

RT-Thread中提供的线程调度器是基于全抢占式优先级的调度,在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自身.系统总共支持256个优先级(0 ~ 255,数值越小的优先级越高,0为最高优先级,255分配给空闲线程使用,一般用户不使用。在一些资源比较紧张的系统中,可以根据情况选择只支持8个或32个优先级的系统配置)。在系统中,当有比当前线程优先级还要高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理机进行执行。

二、线程优先级管理系统

在RT-Thread调度器的实现中,包含了一个共256个优先级队列的数组(如果系统最大支持32个优先级,那么这里将是一个包含了32个优先级队列的数组),每个数组元素中放置相同优先级链表的表头。这些相同优先级的列表形成一个双向环形链表,最低优先级线程链表一般只包含一个idle线程。

在scheduler.c中:

rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

三、线程调度器函数接口(以下函数接口在src/scheduler.c中实现)

调度器初始化:
void rt_system_scheduler_init(void);
在系统启动时需要执行调度器的初始化,以初始化系统调度器用到的一些全局变量。
启动线程调度器:
void rt_system_scheduler_start(void);
在系统完成初始化后切换到第一个线程,可以调用下面的函数接口。
在调用这个函数时,它会查找系统中优先级最高的就绪态线程,然后切换过去执行。另外在调用这个函数前,必须先做idle线程的初始化,即保证系统至少能够找到一个就绪状态的线程执行。此函数是永远不会返回的。
向调度器中添加线程:
void rt_schedule_insert_thread(struct rt_thread *thread);
将线程从调度器中移除:
void rt_schedule_remove_thread(struct rt_thread *thread);
线程调度:
void rt_schedule(void);
让调度器执行一次线程的调度。
调用这个函数后,系统会计算一次系统中就绪态的线程,如果存在比当前线程更高优先级的线程时,系统将切换到高优先级的线程去。上层应用程序一般不需要调用这个函数。

进入临界区,调度器上锁:
void rt_enter_critical(void);
调用这个函数后,调度器将被上锁。在系统锁住调度器的期间,系统依然响应中断,如果中断唤醒了的更高优先级线程,调度器并不会立刻执行它,直到调用解锁调度器函数才尝试进行下一次调度。
同中断锁一样把调度器锁住也能让当前运行的任务不被换出,直到调度器解锁。但和中断锁有一点不相同的是,对调度器上锁,系统依然能响应外部中断,中断服务例程依然能进行相应的响应。所以在使用调度器上锁的方式进行任务同步时,需要考虑好任务访问的临界资源是否会被中断服务例程所修改,如果可能会被修改,那么将不适合采用此种方式进行同步。

退出临界区,调度器解锁:
void rt_exit_critical(void);
当系统退出临界区的时候,系统会计算当前是否有更高优先级的线程就绪,如果有比当前线程更高优先级的线程就绪,将切换到这个高优先级线程中执行;如果无更高优先级线程就绪,将继续执行当前任务。
注:rt_enter_critical/rt_exit_critical可以多次嵌套调用,但每调用一次rt_enter_critical就必须相对应地调用一次rt_exit_critical退出操作,嵌套的最大深度是65535。

返回调度器锁嵌套计数:
rt_uint16_t rt_critical_level(void)
{
    return rt_scheduler_lock_nest;//0表示没有调度器锁
}
调度器锁能够方便地使用于一些线程与线程间同步的场合,由于轻型,它不会对系统中断响应造成负担;但它的缺陷也很明显,就是它不能被用于中断与线程间的同步或通知,并且如果执行调度器锁的时间过长,会对系统的实时性造成影响(因为使用了调度器锁后,系统将不再具备优先级的关系,直到它脱离了调度器锁的状态)。

时间: 2024-12-29 17:13:34

RT-thread内核之线程调度器的相关文章

RT-thread内核之线程调度器分析

一.前言 RT-Thread中提供的线程调度器是基于全抢占式优先级的调度,在系统中除了中断处理函数.调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自身.系统总共支持256个优先级(0 - 255,数值越小的优先级越高,0为最高优先级,255分配给空闲线程使用,一般用户不使用.在一些资源比较紧张的系统中,可以根据情况选择只支持8个或32个优先级的系统配置).在系统中,当有比当前线程优先级还要高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处

RT Thread学习历程(1):串口乱码问题

因为学习实时系统,最近接触到RT Thread. 把RT Thread官网上的示例代码烧录到STM32的板子上之后,在串口软件上接收到的全是乱码,一开始以为是串口软件的问题,换了2个软件之后情况都一样,最后发现是晶振的问题,我用的是STM32F407VGT6,晶振要设为8MHz,代码相应的设置晶振的部分也要修改.

Android异步框架RxJava 1.x系列(三) - 线程调度器Scheduler

前言 RxJava 事件的发出和消费都在同一个线程,基于同步的观察者模式.观察者模式的核心是后台处理,前台回调的异步机制.要实现异步,需要引入 RxJava 的另一个概念 - 线程调度器 Scheduler. 正文 在不指定线程的情况下,RxJava 遵循的是线程不变的原则.即在哪个线程调用 subscribe() 方法,就在哪个线程生产事件:在哪个线程生产事件,就在哪个线程消费事件.如果需要切换线程,就需要用到线程调度器 Scheduler. 1. 几种Scheduler介绍 在 RxJava

RT-thread内核之线程调度算法分析

一个操作系统如果只是具备了高优先级任务能够“立即”获得处理器并得到执行的特点,那么它仍然不算是实时操作系统.因为这个查找最高优先级线程的过程决定了调度时间是否具有确定性,例如一个包含n个就绪任务的系统中,如果仅仅从头找到尾,那么这个时间将直接和n相关,而下一个就绪线程抉择时间的长短将会极大的影响系统的实时性.当所有就绪线程都链接在它们对应的优先级队列中时,抉择过程就将演变为在优先级数组中寻找具有最高优先级线程的非空链表. RT-Thread内核中采用了基于位图(bitmap)的优先级算法(时间复

RT-Thread内核之线程调度(五)

scheduler.c分析 /** * 中断嵌套的层数 */ extern volatile rt_uint8_t rt_interrupt_nest; extern int __rt_ffs(int value); /** * 调度器锁的层数 */ static rt_int16_t rt_scheduler_lock_nest; /** * 线程优先级链表数组: 是一个含有RT_THREAD_PRIORITY_MAX * 个数组元素的链表 */ rt_list_t rt_thread_pri

RT-Thread内核之线程调度(四)

以下为线程部分的源码分析: extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX]; extern struct rt_thread *rt_current_thread; extern rt_list_t rt_thread_defunct; /****************************************************************************************

RT-Thread内核之线程调度(二)

1.什么是临界区? 临界区是指访问共用资源的程序片段.通俗来说,临界区是一段程序代码,但这段代码在访问公共的资源(如全局变量,如某个硬件设备),因此,这段代码的执行必须加锁以保证互斥访问. 2.什么是调度器? 调度器的本质就是一个调度函数,该调度函数的本质就是按照一定的调度算法选出一个最优的个体(线程.进程或任务),并切换到该实体去执行,实质就是让该实体获得CPU的使用权.那么调度器在系统中什么时候会被调用呢?最容易想到的就是系统时钟中断处理程序中,正占用CPU的实体主要让出CPU时,有新的实体

STM32 + RT Thread OS 串口通讯

1.   创建项目 a)   禁用Finsh和console b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因此,在运行scons命令生成项目文件之前,修改rtconfig.h,禁用这两项.(下图L65, L70) c)   生成项目文件 运行scons --target=mdk4 –s 打开生成的项目文件,可以看到,文件组finsh已经不再被包含进来了. d)   创建echo.c 新建一个C文件echo

RT-Thread内核之线程调度(三)

4.RT-Thread中的线程? /** * 线程结构 */ struct rt_thread { /** Object对象 */ char        name[RT_NAME_MAX];                      /**< 线程的名字 */ rt_uint8_t  type;                                   /**< 对象的类型 */ rt_uint8_t  flags;