内核进程调度剖析

1 介绍

对于内核主要分为:进程管理,内存管理,文件系统,内核协议栈四部分。
而对于进程管理主要有创建进程方式,进程调度,内核线程等
进程在内核中描述定义(task_struct)和调度器(sched)

2 调度器

调度器功能是模块化结构,主要工作可以完全由特定调度类方法执行。

cur->sched_class->task_tick(rq,curr,0;

内核核心调度器:主要分为周期性调度器函数和主调度器函数
1 周期性调度器函数
内核中由scheduler_tick()函数实现。
主要工作:
a 更新相关统计量,主要是对各种计数器加1
b 激活负责当前进程的调度类的周期性调度方法。

内核进程调度剖析_第1张图片
更新统计量函数:update_rq_clock()/calc_global_load_tick()

2 主调度器函数
schedule():将cpu使用权从一个进程切换到另一个进程。
主调度器负责将CPU的使用权从一个进程切换到另一个进程。周期性调度器
只是定时更新调度相关的统计信息。cfs队列实际上是用红黑树组织的,rt
队列是用链表组织的。
内核进程调度剖析_第2张图片
cpu核与调度器,调度类以及进程的关系
内核进程调度剖析_第3张图片

3 调度类以及运行队列

a 调度类:内核中sched_class专门抽象的,可动态扩展
目前常见的几种调度类如下:
内核进程调度剖析_第4张图片
b 运行队列
每个处理器都有一个运行队列,结构体是rq,定义的全部变量如下:
内核进程调度剖析_第5张图片
rq是描述就绪队列,其设计为每个cpu就绪队列。

c 调度进程
主要是解决如何调度的问题,主动调度进程的函数是schedule() ,它会把主要工作委托给__schedule()
去处理。
内核进程调度剖析_第6张图片
若为用户进程,调用切换进程时候,也会切换用户虚拟地址空间和寄存器切换。
a 切换用户虚拟地址空间,ARM64架构使用默认的switch_mm_irqs_off,
其内核源码定义如下:
内核进程调度剖析_第7张图片
内核进程调度剖析_第8张图片

b、切换寄存器,宏switch_to把这项工作委托给函数__switch_to:

内核进程调度剖析_第9张图片
内核进程调度剖析_第10张图片
d 调度时机
进程调度何时调度。
调度进程的时机如下:
进程主动调用schedule()函数。
周期性地调度,抢占当前进程,强迫当前进程让出处理器。
唤醒进程的时候,被唤醒的进程可能抢占当前进程。
创建新进程的时候,新进程可能抢占当前进程

如果我们编译内核时开启对内核抢占的支持,那么内核含增加一些指占点。
1 主动调度
用户模式下,无法主动调用schedule(),只能通过系统调用进入内核模式下,等待资源将进程状态设置为睡眠状态,然后主动调用schedule()进程。当然进程也可以通过系统调用sched_yield()让出cpu。
内核3种主动调度方式:
接调用schedule()函数来调用进程。
调用有条件重调度函数cond_resched()。
如果需要等待某个资源。

2 周期调度
通过时钟中断来处理。

4 SMP调度

在smp系统中,进程调度器必须支持如下:
需要使用每个处理器的负载尽可能均衡。
可以设置进程的处理器亲和性,即允许进程在哪些处理器上执行。
可以把进程从一个处理器迁移到另一个处理器。
1 进程的处理器亲和性
设置进程的处理器亲和性,通俗就是把进程绑定到某些处理器,只允许进程在某些处理器上执行,默认情况是进程可以在所有处理器上执行。应用编程接口和使用cpuset配置具体详解分析。
2、期限调度类的处理器负载均衡
限期调度类的处理器负载均衡简单,调度选择下一个限期进程的时候,如果当前正在执行的进程是限期进程,将会试图从限期进程超载的处理器把限期进程搞过来。
内核进程调度剖析_第11张图片
内核进程调度剖析_第12张图片
3、实时调度类的处理器负载均衡
实时调度类的处理器负载均衡和限期调度类相似。调度器选择下一个实时进程时,如果当前处理器的实时运行队列中的进程的最高调度优先级比当前正在执行的进程的调度优先级低,将会试图从实时进程超载的处理器把可推送实时进程拉过来。
内核进程调度剖析_第13张图片

4、公平调度类的处理器负载均衡
目前多处理器系统有两种体系结构:NUMA和SMP。
内部拓扑图如下:
内核进程调度剖析_第14张图片

你可能感兴趣的:(内核专题,内核,多进程,smp)