http://blog.chinaunix.net/uid-20788636-id-1841334.html
在上一篇文章中,我们知道,到 Linux 2.6.23 版本后,linux 实际上维护了一组调度器来实现不同的调度需要,它们被分为了四层:
在上一篇博客 【Linux 内核】进程优先级与调度策略 ① ( SCHED_FIFO 调度策略 | SCHED_RR 调度策略 | 进程优先级 ) 中 , 简单介绍了 " 进程调度策略 " 与 " 进程优先级 " 概念 , 本篇博客开始继续介绍进程调度的代码细节 ;
在Linux中,线程是由进程来实现,线程就是轻量级进程( lightweight process ),因此在Linux中,线程的调度是按照进程的调度方式来进行调度的,也就是说线程是调度单元。Linux这样实现的线程的好处的之一是:线程调度直接使用进程调度就可以了,没必要再搞一个进程内的线程调度器。在Linux中,调度器是基于线程的调度策略(scheduling policy)和静态调度优先级(static scheduling priority)来决定那个线程来运行。
SCHED_RR和SCHED_FIFO是Linux内核中用来调度进程的两种调度策略,它们有以下几点区别:
" 实时进程 " 优先级 高于 " 普通进程 " , 如果当前 Linux 系统的执行队列中有 " 实时进程 " , 调度器 会 优先选择 " 实时进程 " 进行调度 ;
通过此次实验,我将近花了一周的时间去弄懂操作系统linux-2.4.22内核的代码,由于确实在上万行代码的浏览中有些乏力所以写了大量的注释,参考了部分博客,也查阅了大量的资料,回答了实验六要求的六个问题,并提出自己的改进策略:
参考 【Linux 内核】调度器 ⑨ ( Linux 内核调度策略 | SCHED_NORMAL 策略 | SCHED_FIFO 策略 | SCHED_NORMAL 策略 | SCHED_BATCH策略 ) 博客 , 介绍了 Linux 内核相关的调度策略 ;
从Linux 2.6.23开始,默认的调度器为CFS,即"完全公平调度器"(Completely Fair Scheduler)。CFS调度器取代了之前的"O(1)"调度器。
中 , 实现了 获取线程调度策略 , 获取指定调度策略的最大和最小优先级 , 获取线程优先级 , 设置线程调度策略 等功能 ;
" Linux 应用进程 " 可以根据 " Linux 内核 " 提供的 " 调度策略 " 选择 " 调度器 " ;
实时进程和分时进程的调度算法不同,分别在rt.c和fair.c中实现。实时进程的优先级总是高于普通进程。
在 linux-5.6.18\include\linux\sched.h 头文件中 task_struct " 进程描述符 " 结构体 中定义的 sched_class 字段 ,
进程优先级 📷 Linux内核中进程优先级一般分为动态优先级和静态优先级,动态优先级是内核根据进程的nice值、IO密集行为或者计算密集行为以及等待时间等因素,设置给普通的进程;静态优先级是用户态应用设置给实时进程。在调度中静态优先级的进程优先级更高。 📷 一般应用分为IO密集型和计算密集型;I/O密集型是进程执行I/O操作时候等待资源或者事件时候,数据读取到后恢复进程的运行,这样基本出于等待IO和运行之间进行交替,由于具有这样的特性,进程调度器通常会将短的CPU时间片分配给I/O密集型进程。计算密集型是进
调度:就是按照某种调度的算法设计,从进程的就绪队列中选择进程分配CPU,主要是协调进程对CPU等相关资源的使用。
人生不是书上的故事,喜怒哀乐,悲欢离合,都在书页间,可书页翻篇何其易,人心修补何其难。——烽火戏诸侯《剑来》
进程优先级起作用的方式从发明以来基本没有什么变化,无论是只有一个cpu的时代,还是多核cpu时代,都是通过控制进程占用cpu时间的长短来实现的。就是说在同一个调度周期中,优先级高的进程占用的时间长些,而优先级低的进程占用的短些。
在内核中,肯定不能对所有的进程一视同仁,有的进程需要优先运行,有的进程需要运行更长的时间
实时优先级范围是0到MAX_RT_PRIO-1(即99),而普通进程的静态优先级范围是从MAX_RT_PRIO到MAX_PRIO-1(即100到139)。值越大静态优先级越低。
Linux kernel支持两种实时(real-time)调度策略(scheduling policy):SCHED_FIFO和SCHED_RR,无论是哪一种,实时进程的优先级范围[0~99]都高于普通进程[100~139],始终优先于普通进程得到运行。如果实时进程是CPU消耗型的,会不会导致其它进程得不到运行机会,造成系统lockup呢?
进程提供了两种优先级,一种是普通的进程优先级,第二个是实时优先级。前者适用SCHED_NORMAL调度策略,后者可选SCHED_FIFO或SCHED_RR调度策略。任何时候,实时进程的优先级都高于普通进程,实时进程只会被更高级的实时进程抢占,同级实时进程之间是按照FIFO(一次机会做完)或者RR(多次轮转)规则调度的。 1.实时进程的调度 实时进程,只有静态优先级,因为内核不会再根据休眠等因素对其静态优先级做调整,其范围在0~MAX_RT_PRIO-1间。默认MAX_RT_PRIO配置为100,也即,
线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化。我们用pthread_attr_init函数对其初始化,用pthread_attr_destroy对其去除初始化。
在 【Linux 内核】实时调度类 ③ ( 实时调度类 rt_sched_class 源码 | 调度类 sched_class 源码 ) 博客中 , 简单介绍了 实时调度类 rt_sched_class 结构体 , 下面开始分析该结构体的具体字段含义 ,
Android is based on Linux and uses the Linux kernel’s scheduling mechanisms for determining scheduling policies. This is also true for Java code and threads. The Linux’s time sliced scheduling policy combines static and dynamic priorities. Processes can be given an initial priority from 19 to -20 (very low to very high priority). This priority will assure that higher priority processes will get more CPU time when when needed. These level are however dynamic, low level priority tasks that do not consume their CPU time will fine their dynamic priority increased. This dynamic behaviour results is an overall better responsiveness.In terms of dynamic priorities it is ensured that lower priority processes will always have a lower dynamic priority than processes with real-time priorities.Android uses two different mechanisms when scheduling the Linux kernel to perform process level scheduling
今天,继续来讨论哲学话题。什么是真正的公平?给你两个选择,第一:全部人排一样的队,吃一样放的饭,赚一样的钱。第二:人人都分三六九等,有人高高在上事事优先,有人人微言轻事事垫底。你觉得如何?
上一篇博客 【Linux 内核】实时调度类 ① ( 进程分类 | 实时进程、普通进程 | Linux 内核 SCHED_FIFO、SCHED_RR 调度策略 | 实时调度实体 sched_rt_entity ) 引入了 实时调度实体 sched_rt_entity 结构体源码 , 在 Linux 内核源码的 linux-5.6.18\include\linux\sched.h 头文件中 ;
进程调度决定了将哪个进程进行执行,以及执行的时间。操作系统进行合理的进程调度,使得资源得到最大化的利用。
Linux Kernel Development 一书中,关于 Linux 的进程调度器并没有讲解的很全面,只是提到了 CFS 调度器的基本思想和一些实现细节;并没有 Linux 早期的调度器介绍,以及最近这些年新增的在内核源码树外维护的调度器思想。所以在经过一番搜寻后,看到了这篇论文 A complete guide to Linux process scheduling,对 Linux 的调度器历史进行了回顾,并且相对细致地讲解了 CFS 调度器。整体来说,虽然比较啰嗦,但是对于想要知道更多细节的我来说非常适合,所以就有了翻译它的冲动。当然,在学习过程也参考了其它论文。下面开启学习之旅吧,如有任何问题,欢迎指正~
方式一:A 项目做着做着,发现里面有一条指令 sleep,也就是要休息一下,或者在等待某个 I/O 事件。那没办法了,就要主动让出 CPU,然后可以开始做 B 项目。
按照POSIX标准的强制要求,除了“普通”进程之外, Linux还支持两种实时调度类。调度器结构使得实时进程可以平滑地集成到内核中,而无需修改核心调度器,这显然是调度类带来的好处。
在上一节我们了解了CFS的设计原理,包括CFS的引入,CFS是如何实现公平,CFS工作原理的。本小节我们重点在分析CFS调度器中涉及到的一些常见的数据结构,对这些数据结构做一个简单的概括,梳理各个数据结构之间的关系图出来。
结论 虽然平常通过设置为CPU进程数的工作进程,但是可以超过这个数,并且并不是主进程先创建 if (cluster.isMaster) { // 循环 fork 任务 CPU i5-7300HQ 四核四进程 for (let i = 0; i < 6; i++) { cluster.fork() } console.log(chalk.green(`主进程运行在${process.pid}`)) } else { app.listen(1314) // export app 一个
调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个不同的部分, 其中一个涉及调度策略, 另外一个涉及上下文切换.
【引子】周末,读了一篇同事推荐的论文《STUN: Reinforcement-Learning-Based Optimization of Kernel Scheduler Parameters for Static Workload Performance》,很有启发,遂加入个人思考编译成文。
创建Thread时,需要通过参数指定attribute,如果参数为NULL则使用默认值。或者使用pthread_attr_init()初始化一个attribute对象
Linux会把进程分为普通进程和实时进程,普通进程采用CFS之类调度算法,而实时进程则是采用SCHED_FIFO或SCHED_RR。
在 【Linux 内核】实时调度类 ② ( 实时调度实体 sched_rt_entity 源码分析 | run_list、timeout、watchdog_stamp、time_slice 字段 ) 博客中 , 简单介绍了 在 linux-5.6.18\include\linux\sched.h 头文件中定义的 实时调度实体 sched_rt_entity 源码 ,
上一篇博客 【Linux 内核】调度器 ( 调度器概念 | 调度器目的 | 调度器主要工作 | 调度器位置 | 进程优先级 | 抢占式调度器 | Linux 进程状态 | Linux 内核进程状态 ) 介绍了 " 调度器 " 概念 ,
请理解并分析sched_class中各个函数指针的用法,并结合Round Robin 调度算法描ucore的调度执行过程
获取线程调度策略 核心函数 是 pthread_attr_getschedpolicy 函数 ;
实时系统是这样的一种计算系统:当事件发生后,它必须在确定的时间范围内做出响应。在实时系统中,产生正确的结果不仅依赖于系统正确的逻辑动作,而且依赖于逻辑动作的时序。换句话说,当系统收到某个请求,会做出相应的动作以响应该请求,想要保证正确地响应该请求,一方面逻辑结果要正确,更重要的是需要在最后期限(deadline)内作出响应。如果系统未能在最后期限内进行响应,那么该系统就会产生错误或者缺陷。在多任务操作系统中(如Linux),实时调度器(realtime scheduler)负责协调实时任务对CPU的访问,以确保系统中的所有的实时任务在其deadline内完成。
进程可以分为实时进程和普通进程,对于这两种不同类型的进程肯定有不同的调度策略,task_struct中的policy就用来表示调度策略。
本节我们先来学习Linux早期的调度算法的设计,先从最早的调度器算法开始,此调度器时间复杂度是O(n),所以也可以称为O(n)调度算法。我们选择的内核版本是linux-2.4.19。
lab6 会依赖 lab1~lab5 ,我们需要把做的 lab1~lab5 的代码填到 lab6 中缺失的位置上面。练习 0 就是一个工具的利用。这里我使用的是 Linux 下的系统已预装好的 Meld Diff Viewer 工具。和 lab5 操作流程一样,我们只需要将已经完成的 lab1~lab5 与待完成的 lab6 (由于 lab6 是基于 lab1~lab5 基础上完成的,所以这里只需要导入 lab5 )分别导入进来,然后点击 compare 就行了。
Linux进程的调度优先级数字会在好几个地方出现:内核,用户,top命令。他们各自都有自己的表示法。
?在 PM2 的配置文件中可以设置 exec_model:'cluster' 和 instances 两个属性来设置开启多个进程,PM2 其实主要也是利用 Nodejs Cluster 这个模块来实现了,还有 Egg.js 中的 egg-cluster 模块在启动 Worker 进程时也是使用的 Nodejs Cluster 模块。下面来了解下 Nodejs Cluster 这个模块做了什么?
因而内核提供了两个调度器主调度器,周期性调度器,分别实现如上工作, 两者合在一起就组成了核心调度器(core scheduler), 也叫通用调度器(generic scheduler).
int pthread_create((pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) 若线程创建成功,则返回0。若线程创建失败,则返回出错编号,并且*thread中的内容是未定义的
领取专属 10元无门槛券
手把手带您无忧上云