Linux内核(三)进程调度

转载请注明出处:jiq?钦‘s
technical Blog

数据结构:

每个处理器维护一个运行队列,主要字段如图所示。

每个运行队列有两个优先级队列,一个活跃的(时间片未完),另一个是过期的(时间片已完)。每个队列都有一个位图,用于快速寻找到当前队列中的最高优先级。

Schedule()函数执行步骤如下:

(1)在活动优先级队列的位图数组中找到当前最高优先级;

(2)按照这个优先级数值查找优先级数组,然后在挂在该位置的进程队列(具有相同优先级)上面取下第一个;

(3)如果不是当前正在运行的进程,则做任务切换(调用context_switch()函数)。

何时调用schedule()函数?

(1)当前进程休眠(阻塞)(主动):将自己标记为休眠状态,把自己从可执行队列移除放入等待队列,然后调用schedule()函数;

(2)当前进程结束(主动):执行do_exit()函数的最后一个步骤,就是调用schedule()函数;

(3)被抢占(被动):这是最为复杂的部分,主要靠一个“全局标志”need_resched完成。

两种情况下这个标志会被设置:

(I)当某个进程时间片耗尽时scheduler_tick()函数设置;

(II)当一个高优先级任务进入就绪态时try_to_wake_up()函数设置;

标志虽然设置了,但是没有真正启动调度器,什么时候启动呢?

I)用户抢占:

1 执行系统调用(利用中断实现)返回用户空间时检查need_resched标志,如果被设置了就启用调度器:

2 执行中断处理程序返回用户空间时检查need_resched标志,如果被设置了就启用调度器;

II)内核抢占:

注:增加一个标志preempt_count表示当前运行任务(current)所持有锁的数量。

1 中断处理程序返回内核空间时检查如果need_resched标志被设置,并且preempt_count标志值为0,则启用调度器;

2 当前进程执行释放锁的代码会检查preempt_count值若为0(没有持有锁了)并且设置了need_resched标志,则启用调度器;

3 内核显示调用schedule()函数;

注:可以使用preempt_disable()/preempt_enable()函数对禁止和允许内核抢占。

Linux进程调度策略:

多任务,抢占式。

基于优先级调度,时间片轮转。

动态优先级,动态时间片。

或者说:

优先级高的先运行,低的后运行,相同优先级的按轮转方式调度。

调度程序总是选择时间片未用尽且优先级最高的进程运行
!!!

动态优先级如何计算?

每个任务两个优先级:

(1)一个静态优先级。作为初始优先级+作为计算动态优先级基础;

(2)一个动态优先级。其值
= 静态优先级+交互性强度(基于任务休眠时间来计算);

因为我们需要动态提高交互性强的I/O消耗型任务的优先级,I/O消耗型任务执行频率高,执行时间短,休眠时间长,交互性强度高,所以导致动态优先级高。

动态时间片如何计算?

优先级越高,时间片越长,nice(优先级数值)越小,执行频率越高!!!

(比如I/O消耗型)

可见优先级和时间片长度成正比!!!

所以只需要将优先级按一定比例缩放,符合时间片数值范围,就是时间片值了。

如何保证交互性强的任务(如I/O消耗性)执行频率高?

在schedler_tick()函数中:

(1) 当前任务时间片减一操作;

(2)若减为零,判断如果不是交互性强的任务或者过期数组中存在“饥饿进程”,则将当前任务加入过期数组;

否则加入活跃数组(这样就保证了执行频率高些)。

也就是说每个时钟周期会检查一次,将交互性强的任务再放回到活跃数组,让其尽快有机会再次得到执行。

时间: 2024-12-27 23:56:45

Linux内核(三)进程调度的相关文章

Linux内核三位数表示的含义

Linux内核由C语言编写,但是Linux内核并不能称为操作系统,内核只提供基本的设备驱动.文件管理.资源管理等功能.是Linux操作系统的核心组件,Linux内核可以被广泛移值,而且还对多种硬件都适用. Linux内核 版本有稳定版和开发版两种.Linux内核版本号一般由三位数字组成,比如2.6.18内核版本: 第一组数字2表示目前发布的内核主版本 第二组数字6表示稳定版本,如为奇数则表示开发中版本 第三组数字18表示修改的次数

Linux内核开发 — 进程调度

本节简单介绍内核开发中,进程调度的相关知识点. 什么是进程调度 进程调度就是在已经就绪的进程中选择一个最合适的进程执行的过程. 进程调度策略 实时类调度策略 非实时类调度策略 进程调度时机 主动式抢占 当前进程因为需要等待资源等原因主动放弃执行权限,主动要求切换到下一个进程执行. 主动放弃CPU的例子: current->state = TASK_INTERRUPTIBLE;               schedule(); 被动式抢占 当前进程因为优先级.进程属性等原因被迫让出CPU执行权限

free-electrons linux内核和驱动

操作系统的三个作用:1.管理硬件资源:2.提供独立于架构和硬件的可移植的软件接口3.处理不同应用对相同硬件资源的同时访问 系统调用接口是稳定的,系统调用由c函数库封装,用户程序基本不需要直接调用系统函数. linux系统通过虚拟文件系统向用户空间提供系统和内核信息,虚拟文件系统允许应用程序访问实际存储空间不存在的文件和目录,虚拟文件系统由内核动态创建. 最重要的两个虚拟文件系统是/proc 和/sysfs这两个文件系统 proc挂载在/proc目录下,提供操作系统的一些信息如进程信息和内存参数管

linux内核的组成,王明学learn

linux内核的组成 一.linux内核源代码目录结构 arch: 包含和硬件体系结构相关的代码, 每种平台占一个相应的目录, 如 i386.ARM.PowerPC.MIPS 等. block:块设备驱动程序 I/O 调度. crypto:常用加密和散列算法(如 AES.SHA 等) ,还有一些压缩和 CRC 校验算法. Documentation:内核各部分的通用解释和注释. drivers:设备驱动程序,每个不同的驱动占用一个子目录,如 char.block.net.mtd .i2c 等.

Linux 内核同步机制

    本文将就自己对内核同步机制的一些简要理解,做出一份自己的总结文档.     Linux内部,为了提供对共享资源的互斥访问,提供了一系列的方法,下面简要的一一介绍. Technorati 标签: 互斥 Linux 中断屏蔽 使用方法: local_irq_disable() //屏蔽中断 critical section //临界区 local_irq_enable() //开中断 .csharpcode, .csharpcode pre { font-size: small; color

【读书笔记】《Linux内核设计与实现》进程管理与调度

大学跟老师做嵌入式项目,写过I2C的设备驱动,但对Linux内核的了解也仅限于此.Android系统许多导致root的漏洞都是内核中的,研究起来很有趣,但看相关的分析文章总感觉隔着一层窗户纸,不能完全理会.所以打算系统的学习一下Linux内核.买了两本书<Linux内核设计与实现(第3版)>和<深入理解Linux内核(第3版)> 0x00 一些废话 面向对象思想. Linux内核虽然是C和汇编语言写的,没有使用面向对象的语言,但里面却包含了大量面向对象的设计.比如可以把内核中的进程

linux内核---嵌入式linux内核的五个子系统

转自:https://blog.csdn.net/qq_27522735/article/details/63251168 Linux内核主要由进程调度(SCHED).内存管理(MM).虚拟文件系统(VFS).网络接口(NET)和进程间通信(IPC)5个子系统组成,如图1所示. 图1 Linux内核的组成部分与关系 1.进程调度 进程调度控制系统中的多个进程对CPU的访问,使得多个进程能在CPU中"微观串行,宏观并行"地执行.进程调度处于系统的中心位置,内核中其他的子系统都依赖它,因为

Linux内核设计第八周学习总结 理解进程调度时机跟踪分析进程调度与进程切换的过程

陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频内容 Linux系统的一般执行过程 最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程 1. 正在运行的用户态进程X 2. 发生中断——save cs:eip/esp/eflags(current) to kernel stack, then load cs:eip(entry of a specific IS

linux内核分析 第三周 构造一个简单的Linux系统MenuOS

一.计算机的三个法宝 存储程序计算机,函数调用堆栈,中断二.操作系统的两把剑:1.中断上下文的切换,保存现场和恢复现场2.进程上下文的切换. 三.linux内核源代码的分析: ·arch/目录保存支持多种CPU类型的源代码,重点是x86·init目录:含有main.c,内核启动相关的代码基本都在init目录下·ipc目录:进程间的通信·kernel目录:有Linux内核的核心代码.四.构造一个简单的Linux系统 使用实验楼的虚拟机打开shell 1.cd LinuxKernel/2.qemu