linux 进程调度源码分析,Linux调度器源码分析

代码分析根据3.10版本

通过对前面的学习我们知道Linux的调度分为两种

周期调度 完成周期性算法参数的更新和系统其它实际的检查

主调的 真正的调度过程

我们现在来看下主调的的代码框架。

入口

根《调度发生的情况》的学习,我们知道所有的调度最后都会到 schedule 函数中。因此我们就先从schedule函数入手。

asmlinkage void __sched schedule(void)

{

struct task_struct *tsk = current;

sched_submit_work(tsk);//获取当前current 并且加锁。

__schedule();

}

schedule 函数并没有太多的操作,只是获取当前task,然后加锁,最后都交给了**__schedule()**函数。

主要框架

主要函数__schedule分析

static void __sched __schedule(void)

{

struct task_struct *prev, *next;

unsigned long *switch_count;

struct rq *rq;

int cpu;

need_resched:

preempt_disable();

cpu = smp_processor_id();

rq = cpu_rq(cpu);//找到当前cpu拿取队列

prev = rq->curr;//保持此时此刻的任务

.....

pre_schedule(rq, prev);//做一些预处理

....

put_prev_task(rq, prev);

next = pick_next_task(rq);//选取下一个进程

clear_tsk_need_resched(prev);

rq->skip_clock_update = 0;

if (likely(prev != next)) {//选好了,

rq->nr_switches++;

rq->curr = next;

++*switch_count;//计数加一

...

context_switch(rq, prev, next); /* unlocks the rq */真正的切换堆栈帧

...

cpu = smp_processor_id();

rq = cpu_rq(cpu);

} else

raw_spin_unlock_irq(&rq->lock);

....

if (need_resched())//是否需要重新调度

goto need_resched;

}

其实**__schedule**还是比较长的,但是我们这里选择了一些主要的流程分析,流程如下:

1、拿到当前cpu的队列rq

2、进行一些与操作处理

3、选取下一个进程

4、堆栈帧context_switch 切换

5、是否需要重新调度

关于重新调度,设计到一些内核抢占的知识,我们暂时不分析。而context_switch,是硬件堆栈的切换,我们后文会认真分析这个函数,在这个过程中我们主要关注如何选取下一个进程。

如何选取下一个任务 pick_next_task 函数分析

static inline struct task_struct * pick_next_task(struct rq *rq)

{

const struct sched_class *class;

struct task_struct *p;

/*

* Optimization: we know that if all tasks are in

* the fair class we can call that function directly:

*/

if (likely(rq->nr_running == rq->cfs.h_nr_running)) {检查当前cpu队列中是否所有的都是cfs,如果是就直接掉用cfs的调度类

p = fair_sched_class.pick_next_task(rq);

if (likely(p))

return p;

}

for_each_class(class) {循环遍历每一个调度类

p = class->pick_next_task(rq);

if (p)

return p;

}

}

pick_next_task 还是比较简单的只是有两部, 1、查看当前cpu队列是否所有的都是cfs 2、遍历所有调度类。 对于是不是全部cfs的检查是有必要的,会减少开销。我们再来看下遍历

#define sched_class_highest (&stop_sched_class)

#define for_each_class(class) \

for (class = sched_class_highest; class; class = class->next)

extern const struct sched_class stop_sched_class;

extern const struct sched_class rt_sched_class;

extern const struct sched_class fair_sched_class;

extern const struct sched_class idle_sched_class;

我们看到是从stop_sched_class开始,

const struct sched_class stop_sched_class = {

.next= &rt_sched_class,

....

}

const struct sched_class rt_sched_class = {

.next= &fair_sched_class,

....

}

const struct sched_class fair_sched_class = {

.next= &idle_sched_class,

....

}

const struct sched_class idle_sched_class = {

/* .next is NULL */

....

}

可以看到是这么个列表。

stop_sched_class --》rt_sched_class--》fair_sched_class--》idle_sched_class--》NULL

以cfs为例看看如何选取task

static struct task_struct *pick_next_task_fair(struct rq *rq)

{

struct task_struct *p;

struct cfs_rq *cfs_rq = &rq->cfs;

struct sched_entity *se;

if (!cfs_rq->nr_running)

return NULL;

do {

se = pick_next_entity(cfs_rq);

set_next_entity(cfs_rq, se);

cfs_rq = group_cfs_rq(se);

} while (cfs_rq);

p = task_of(se);

if (hrtick_enabled(rq))

hrtick_start_fair(rq, p);

return p;

}

这部分代码也是组调度流程的基础,现在看起来是比较简单的,但是接下来分析组调度的时候就会详细的展开分析。 我们看这个简单的过程:

全局的rq 拿到cfs_rq

cfs_rq 通过pick_next_entity 拿到算法算好的调度类entity----se。

进行组调度----目前先忽略

将se 转换成task 这样就结束了主调的的所有过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/528027.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux修改端口cost值,Linux下通过修改网卡驱动的参数调整Intel网卡的性能

下面列出paramerter中和性能相关的几个以及他们的取值范围和默认值。InterruptThrottleRate范围:100-100000 (0off, 1dynamic)默认:0注:不支持82542, 82543, 82545, 82544芯片RxDescriptors范围:80-256 for 82542 and 82543-based…

Linux跑齿轮命令,【转】glxgears命令

glxgears是一个测试你的Linux是否可以顺利运行2D、3D的测试软件。这个程序弹出一个窗口,里面有三个转动的齿轮,屏幕将显示出每五秒钟转动多少栅,所以这是一个合理的性能测试。窗户是可以缩放的,栅数多少极大程度上依赖于窗口的大小…

log4j日志 linux配置,Log4j 日志详细用法

简单的说log4j就是帮助开发人员进行日志输出管理的API类库。它最重要的特点就可以配置文件灵活的设置日志信息的优先级、日志信息的输出目的地、日志信息的输出格式Log4j 除了可以记录程序运行日志信息外还有一重要的功能就是用来显示调试信息。程序员经常会遇到脱离Java ide环…

linux 改目录前缀,Linux修改终端显示前缀及环境变量

Linux终端前面默认显示一长串,如:这是由PS1环境变量决定的:[[email protected] dir]$ echo $PS1[\u\H \W]\$其中\u代表用户,\H代表主机,\W代表目录可以修改环境变量,有三种方法:1. 直接修改&…

linux qtcreator输入中文,新版QT creator下解决fcitx无法输入中文问题(QTcreatorV4.1.0)...

Preface新版本的QT creatorV4.0.0之后,就QT creator结构本身就发生了很大的变化,许多文件路径以及结构都发生了较大的变化。因此,fcitx的qt5库位置也发生了变化,但是原理还是一样的,都是需要一个动态依赖库&#xff1a…

lisp 读取dwg 统计信息_预制梁厂 BIM 技术和自动化、信息化应用方案

一、使用 Planbar 桥梁模块进行 BIM 模型创建Planbar是德国内梅切克软件工程有限公司专门针对混凝土图纸构件的软件产品,通过三十多年专注于预制构件设计工作所累积的经验,PLANBAR 实现了无与伦比的规划深度。PLANBAR 支持 40 种以上的数据交换形式&…

windows os x linux比较,对比测试:Ubuntu 11.04 vs Win7 vs OS X 10.7

今天我们带来了关于Ubuntu 11.04,Windows 7,Mac OS X 10.7的对比测试,包括图片编辑、视频编码、多任务测试等。本次测试是在同一机子上展开的,这样避免了硬件的因素影响。Ubuntu 11.04,Mac OS X 10.7硬件参数&#xff…

简述osi参考模型各层主要功能_OSI网络模型

OSI七层模型和TCP/IP五层模型 一、OSI参考模型 1、OSI的来源 OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互连模型。 ISO为了更好的使网络应用更为普及,推出了OSI参考模型。其含义就是推荐所有…

linux 线程优先级算法,能讲一下在Linux系统中时间片是怎么分配的还有优先级的具体算法是...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼图 1 RT-Linux结构RT -Linux的关键技术是通过软件来模拟硬件的中断控制器。当Linux系统要封锁CPU的中断时时,RT-Linux中的实时子系统会截取到这个请求,把它记录下来,而实际上并不真正封锁硬件中断…

python linux log,linux,python 常用的处理log的命令

一般的log文件都是需要过滤ps:管道符| 管道符前面的输出值grep 过滤查找将是error的log过滤显示grep 221.2.100.138 web.access.loggrep 221.2.100.138 web.access.logless web.access.log |grep "221.2.100.138"统计error行数grep 221.2.100.138 web.access.log |…

vue 图片自适应排列插件_将一堆图片自适应页面排列

最近在开发一个批量展示图片的页面,图片的自适应排列是一个无法避免的问题在付出了许多头发的代价之后,终于完成了图片排列,并封装成组件,最终效果如下一、设计思路为了使结构清晰,我将图片列表处理成了二维数组&#…

linux中vi基础知识,Vim入门基础知识集锦

想学习Vim,但是Vim官网的手册又太大而全,而网上各方资料要么不全面,要么不够基础。在网上搜集各方资料,按照自己的框架整理一份Vim入门基础教程,分享出来。特点是偏向基础,但对入门者来说足够全面&#xff…

60度斜坡怎么计算_坡度怎么计算

展开全部表示坡度最为常用的方法,即两点的高程差与其路程的百e69da5e6ba9062616964757a686964616f31333431356636分比,其计算公式如下:坡度 (高程差/路程)x100%。坡度的表示方法有百分比法、度数法、密位法和分数法四种,其中以百…

linux go missing git command,安装beego出现go: missing Git command

安装beego报下面的错误:go build -ldflags "-linkmode external -extldflags -static" -o go-admin main.gomain.go:5:2: cannot find package "github.com/astaxie/beego" in any of:D:\Go\src\github.com\astaxie\beego (from $GOROOT)F:\xia…

串口 多个activity 安卓_Android-EasySerialPort

Android-EasySerialPort非常好用、非常稳定的Android串口封装久经两年多项目考验,一直很稳定使用说明第一步,在gradle(Project)下添加allprojects {repositories {...maven { url https://www.jitpack.io }}}第二步,导入依赖dependencies {im…

linux bluez语音传输,Linux BlueZ PCM 音频播放器

自己写的简单的实验代码,贴上来看看,有兴趣的话,大家可以交流/******************************************************************************//** …

光纤收发器的原理及应用_光纤收发器的工作原理及使用方法介绍

关于光纤收发器的工作原理以及使用方法这块,在这里飞畅科技的小编做了专门的整理,首先,我们来了解下什么是光纤收发器,光纤收发器是一种将短距离的双绞线电信号和长距离的光信号进行互换的以太网传输媒体转换单元,在很…

变频器按启动没反应_ABB变频器启动无反应维修那些事

[标题]常州凌科自动化是电路板芯片级维修服务商,有健全的维修中心,致力于各类复杂工控电气设备修复工作。我们有十年变频器维修经验的技术工程师、安装人员组成的强大技术队伍;充分利用自己己有的人才、测试设备、试验平台、为企业提供先进、…

C语言编程序1到100的素数,c语言输出100以内素数 c语言编程输出1到100之间素数并求和,在线等,急?...

C语言,编写函数判断一个整数是否为素数,在主函数中调用该函数并输出100以内的全部素数?参考代码:#include &ltstdio.h&gtint is_prime_number(int n){int iint result 1if(n1)return 0for(i2i&ltni ){if(n%i0){resul…

用jsonserve和axios做交互_详解解决使用axios发送json后台接收不到的问题

问题描述按照axios官网例子发起请求传递json,后台接受到的数据为空,一直卡在options阶段。尝试的方法开始以为是接口有问题,使用postman测试下,一切正常,百思不得其解,看了好多issue也解决不了,…