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

一、前言

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];

三、线程调度器函数接口

调度器初始化:
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;
}
调度器锁能够方便地使用于一些线程与线程间同步的场合,由于轻型,它不会对系统中断响应造成负担;但它的缺陷也很明显,就是它不能被用于中断与线程间的同步或通知,并且如果执行调度器锁的时间过长,会对系统的实时性造成影响(因为使用了调度器锁后,系统将不再具备优先级的关系,直到它脱离了调度器锁的状态)。
时间: 2024-08-05 10:52:21

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

RT-thread内核之线程调度器

http://www.cnblogs.com/King-Gentleman/p/4278012.html 一.前言 RT-Thread中提供的线程调度器是基于全抢占式优先级的调度,在系统中除了中断处理函数.调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自身.系统总共支持256个优先级(0 - 255,数值越小的优先级越高,0为最高优先级,255分配给空闲线程使用,一般用户不使用.在一些资源比较紧张的系统中,可以根据情况选择只支持8个或32个优先

第一次作业:Linux 2.6.32的进程模型与调度器分析

1.前言 本文分析的是Linux 2.6.32版的进程模型以及调度器分析.在线查看 源码下载 本文主要讨论以下几个问题: 什么是进程?进程是如何产生的?进程都有那些? 在操作系统中,进程是如何被管理以及它们是怎样被调用的? 2.进程模型 2.1进程的概念 在我的理解中,一个程序就相当于一个进程,程序的启动意味着产生了一个新的进程,程序的关闭也就意味着一个进程的消亡. 那么专业定义应该是: 在计算中,进程是正在执行的计算机程序的一个实例. 它包含程序代码及其当前活动. 根据操作系统(OS),一个进

FreeBSD 内核中的SYSINIT分析【转】

FreeBSD?kernel是一个膨大的系统,?对于这样一个大系统,?里面往往包含了大量的子系统和??模块,当系统初始化时这些模块就需要初始化,?按照通常的思路,这些初始化过程必须在某处??被显式地调用,这样一来,当你新增某个模块,你必须再修改那个系统初始化的地方来调用这??个新增模块的初始化过程,?而且由于ANSI?C语言的限制,调用某个函数最好先声明,这样当系??统的初始化过程开始增加时,?那个调用初始化过程的文件开始大量包含那些本来不相关的头??文件,?偶合度就增加了,?这是一种不好的设计

Linux内核抢占实现机制分析【转】

Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介绍了内核抢占和用户抢占的概念和区别,接着分析了不可抢占内核的特点及实时系统中实现内核抢占的必要性.然后分析了禁止内核抢占的情况和内核抢占的时机,最后介绍了实现抢占内核所做的改动以及何时需要重新调度. [关键字]内核抢占,用户抢占,中断, 实时性,自旋锁,抢占时机,调度时机,schedule,pree

Linux内核抢占实现机制分析

Sailor_forever  [email protected] 转载请注明 http://blog.csdn.net/sailor_8318/archive/2008/09/03/2870184.aspx [摘要]本文详解了Linux内核抢占实现机制.首先介绍了内核抢占和用户抢占的概念和区别,接着分析了不可抢占内核的特点及实时系统中实现内核抢占的必要性.然后分析了禁止内核抢占的情况和内核抢占的时机,最后介绍了实现抢占内核所做的改动以及何时需要重新调度. [关键字]内核抢占,用户抢占,中断, 

Linux内核--网络栈实现分析(七)--数据包的传递过程(下)

本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地址http://blog.csdn.net/column/details/linux-kernel-net.html 作者:闫明 注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析.”(下)“表示分析是从上向下分析. 在博文Linux内核--网络栈

类加载器分析(JVM)

最近去了解了下关于java虚拟机中的加载机制,特地写了篇blog来记忆下. 首先我们来了解下概念,什么是类加载器? A:加载器就是把java的字节码从硬盘中加载到内存,然后再做一些处理,这就是类加载器所做的一些工作 默认情况下:java有默认的三个类加载器,(树状结构)从上到下分别是bootStrap.ExtClassLoader.AppClassLoader三个加载器 本质上java的类加载器为一个java类,当然也有一个是特殊的,就比如说第一个加载器bootStrap是用C++写的 优先级是

Linux内核态抢占机制分析(转)

Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核(Preemptive Kernel)的区别.接着分析Linux下有两种抢占:用户态抢占(User Preemption).内核态抢占(Kernel Preemption).然后分析了在内核态下:如何判断能否抢占内核(什么是可抢占的条件):何时触发重新调度(何时设置可抢

第一次作业:关于Linux进程模型及CFS调度器分析

第一次作业内容 挑选一个开源的操作系统,深入源码分析其进程模型,具体包含如下内容: 操作系统是怎么组织进程的 进程状态如何转换(给出进程状态转换图) 进程是如何调度的 谈谈自己对该操作系统进程模型的看法 1. 前言 本文基于Linux Kernel 2.6.28 的源代码,分析本版本linux的进程模型和CFS调度器的基本算法. 源码浏览地址:https://elixir.bootlin.com/linux/v2.6.28/source 2. 进程 2.1 进程的定义 <计算机操作系统>这门课