01.4进程原理和系统调用--->经典的CFS调度器

news2024/10/7 2:31:15

进程的一些正常状态

什么是进程

操作系统作为硬件的使用层,提供使用硬件资源的能力,进程作为操作系统使用层,
提供使用操作系统抽象出的资源层的能力。
进程:是指计算机中已运行的程序。进程本身不是基本的运行单位,而是线程的容器。
程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行
实例。
在这里插入图片描述

进程间的关系

在这里插入图片描述
linux提供一些api进行上面状态的查询 查看当前这个进程的状态
●TASK_ RUNNING (可运行状态或者可就绪状态) ;
●TASK INTERRUPTIBLE (可中断睡眠状态,又叫浅睡眠状态) ;
●TASK UNINTERRUPTIBLE (不可中断状态,又叫深度睡眠状态) ;我们可以通过ps命令查看被标记为D状态
●TASK_ STOPPED (终止状态) ;
●EXIT_ ZOMBIE (僵尸状态) ;

进程结构体

Linux内核涉及进程和程序的所有算法都围绕一个名为task_struct的数据结构建立,该结构定义在include/linux/sched.h中。这是系统中主要的一个结构。在阐述调度器的实现之前,了解一下Linux管理进程的方式是很有必要的。
task_struct包含很多成员,将进程与各个内核子系统联系,task_struct定义如下

struct task_struct {
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */ 进程状态标志
	void *stack; 指向内核栈
	atomic_t usage;
	unsigned int flags;	/* per process flags, defined below */
	unsigned int ptrace;
	pid_t pid;  //全局进程号
	pid_t tgid; //全局线程号
	struct pid_link pids[PIDTYPE_MAX]; //进程组标识符和会话标识符,进程号
	struct task_struct __rcu *real_parent; /* real parent process */ 真父进程号
	struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */ 父进程号
	struct task_struct *group_leader;	/* threadgroup leader */  指向线程组的组长
	const struct cred __rcu *real_cred; /* objective and real subjective task  指向证书
					 * credentials (COW) */
	const struct cred __rcu *cred;	/* effective (overridable) subjective task*/
	char comm[TASK_COMM_LEN]; //进程名称
	int prio, static_prio, normal_prio; //调度策略的优先级
	prio //动态优先级
	static_prio//每个进程刚开始就分配了静态优先级,使用nice和set_shell来修改
	normal_prio//动态优先级
	unsigned int rt_priority;//实时进程优先级,不会带入之前说的值
	const struct sched_class *sched_class;//表示该进程所属的调度器的类    


		cpumask_t cpus_allowed;//是否运行在cpu上运行
	int nr_cpus_allowed;//允许这个进程在哪个cpu上运行
	struct mm_struct *mm, *active_mm;//这两个指针指向内存描述符
	//在进程中,mm和active_mm指向同一个内存描述符
	//内核线程中mm就是空指针,当内核线程运行的时候active_mm指向进程借用一个内存描述符
	struct fs_struct *fs; //指向文件系统,主要为进程根目录和当前进程工作目录
	struct files_struct *files; //打来的文件列表
	//下面用于做信号处理
	struct signal_struct *signal;
	struct sighand_struct *sighand;

	sigset_t blocked, real_blocked;
	sigset_t saved_sigmask;	/* restored if set_restore_sigmask() was used */
	struct sigpending pending;
/* ipc stuff *///下面两个用于unix信号量和共享内存
	struct sysv_sem sysvsem;
	struct sysv_shm sysvshm;
	....}

进程优先级

1、进程优先级
总体排序 : 限期进程的优先级比实时进程要高,实时进程的优先级比普通进程要高。
➢限期进程的优先级是-1;
➢实时进程的优先级1-99,优先级数值越大,表示优先级越高;
➢普通进程的静态优先级为: 100-139, 优先级数值越小,表示优先级越高,可通过修改
nice值改变普通进程的优先级,优先级等于120加上nice值。
2、 并非所有进程都具有相同的重要性。
除了大多数我们所熟悉的进程优先级之外,进程还有不同的关键度类别,以满足不同需求。首先进行比较粗糙的划分,进程可以分为实时进程和非实时进程(普通进程)。
实时进程优先级(0-99)都比普通 进程的优先级(100-139)高。当系统中有实时进程运行时,普通进程几乎无法分到赶时间片(只能分到5%的CPU时间)
下面的优先级也对应了四个属性, 不同的进程使用哪个属性比较当前的优先级
在这里插入图片描述

如何创建进程

1用户进程

传统的UNIX中用于复制进程的系统调用是fork。但它并不是Linux为此实现的唯一调用,实际上Linux实现了3个。
(1) fork是重量级调用,因为它建立了父进程的一个完整副本,然后作为子进程执行。为减少与该调用相关的工作量,Linux使用了写时复制(copy-on-write)技术。
(2) vfork类似于fork,但并不创建父进程数据的副本。相反,父子进程之间共享数据。这节省了大量CPU时间(如果一个进程操纵共享数据,则另一个会自动注意到)。
(3) clone产生线程,可以对父子进程之间的共享、复制进行精确控制。
进程系统调用
【写时复制】
内核使用了写时复制(Copy-On-Write,COW)技术,以防止在fork执行时将父进程的所有数据
复制到子进程。在调用fork时,内核通常对父进程的每个内存页,都为子进程创建一个相同的副本。
【执行系统调用】
fork、vfork和clone系统调用的入口点分别是sys_fork、sys_vfork和sys_clone函数。其定义依赖于
具体的体系结构,因为在用户空间和内核空间之间传递参数的方法因体系结构而异。
【do_fork实现】
所有3个fork机制最终都调用kernel/fork.c中的do_fork(一个体系结构无关的函数)

2内核线程

内核线程是直接由内核本身启动的进程。内核线程实际上是将内核函数委托给独立的进程,与系统中其他进程“并行”执行(实际上,也并行于内核自身的执行)。内核线程经常称之为(内核)守护进程。它们用于执行下列任务
周期性地将修改的内存页与页来源块设备同步(例如,使用mmap的文件映射)。
• 如果内存页很少使用,则写入交换区。
• 管理延时动作(deferred action)。
• 实现文件系统的事务日志

3图片示例

上面的用户进程使用 fork() vfork() do_fork()
和内核线程中的kthread_creat() 从源码里分析都是用到了do_fork()这个函数
在这里插入图片描述

CFS调度器

调度器是啥

调度器 Linux内核中用来安排调度进程(-一段程序的执行过程)执行的模块称为调度器(Scheduler),它可以切换进程状态(Process status)。比如:执行、可中断睡眠、不可中断睡眠、退出、暂停等。
在这里插入图片描述
调度器是CPU中央处理器的管理员,主要负责完成做两件事情:
一、选择某些就绪进程来执行,
二是打断某些执行的进程让它们变为就绪状态。调度器分配CPU时间的基本依据就是进程的优先级。
上下文切换(context switch):将进程在CPU中切换执行的过程,内核承担此任务,负责重建和存储被切换掉之前的CPU状态。

调度器类定义

sched_class结构体表示调度类,定义在kernel/sched/sched.h
Linux调度类:dl_sched_class、rt_sched_class、fair_sched_class及idle_sched_class等。每个进程都有一个自己的调度策略
每个调度策略对应一种调度类
在这里插入图片描述
在这里插入图片描述
这5种调度类的优先级从高到低依次为:停机调度类、限期调度类、实时调度类、公平调度类、空闲调度
类。
●停机调度类:优先级是最高的调度类,停机进程是优先级最高的进程,可以抢占所有其它进程,其他进
程不可能抢占停机进程。
●限期调度类:最早使用优先算法,使用红黑树把进程按照绝对截止期限从小到大排序,每次调度时选择
绝对截止期限最小的进程。
●实时调度类:为每个调度优先级维护-一个队列。
●公平调度类:CFS用于一般线程 使用完全公平调度算法。完全公平调度算法引入虚拟运行时间的相关概念:虚拟运行时间=
实际运行时间*nice0对应的权重/进程的权重。
●空闲调度类:每个CPU上有一个空闲线程,即0号线程。空闲调度类优先级别最低,仅当没有其他进程可
以调度的时候,才会调度空闲线程。每个CPU的第一个PID=0线程,swapper,是一个静态线程。调度类属
于idel sched class。 一般运行在开机过程和CPU异常的时候会做dump.
Linux调度核心选择下一个合适的task运行时,会按照优先级顺序遍历调度类的pick_ next. _task函数。

进程优先级

task_ struct结构体中采用3三个成员表示进程的优先级: prio和normal_ prio表示动态优先
级, static_ prio表示进程的静态优先级。
内核将任务优先级划分,实时优先级范围是0到MAX_ RT_ PRIO-1 (即99) , 而普通进程
的静态优先级范围是从MAX_ RT_ PRIO到MAX_ PRIO-1 (即100到139) 。
这种粗糙的划分,进程可以分为实时进程和非实时进程(普通进程)
实时进程(Real-Time Process) :优先级高、需要立即被执行的进程。
普通进程(Normal Process) :优先级低、更长执行时间的进程。
进程的优先级是一I -个0–139的整数直接来表示。数字越小,优先级越高,其中优先级0-99留给实时进程,
100-139留给普通进程。
实时进程优先级(0-99)都比普通 进程的优先级(100-139)高。当系统中有实时进程
运行时,普通进程几乎无法分到赶时间片(只能分到5%的CPU时间)。
在这里插入图片描述

内核调度策略

有了上面的进程优先级和各种调度器类,这时候linux内核会提供一些调度策略给应用程序来选择调度器
在这里插入图片描述
SCHED_ NORMAL: 普通进程调度策略,使task选择CFS调度器来调度运行:
SCHED_ FIFO: 实时进程调度策略,先进先出调度没有时间片,没有更高优先级的状态下,只有等待主动
让出CPU;
SCHED_ RR:实时进程调度策略,时间片轮转,进程使用完时间片之后加入优先级对应运行队列当中的尾
部,把CPU让给同等优先级的其它进程;
SCHED_ BATCH:普通进程调度策略,批量处理,使task选择CFS调度器来调度运行;
SCHED_ JIDLE: 普通进程调度策略,使task以最低优先级选择CFS调度器来调度运行:
SCHED_ DEADLINE: 限期进程调度策略,使task选择Deadline调度 器来调度运行;
备注:其中stop调度器和DLE-task调度器,,仅使用于内核,用户没有办法进行选择。
在一个进程的结构体中,下面这个属性来表示这个进程所属的调度器类
在这里插入图片描述

完全公平调度器CFS

完全公平调度算法体现在对待每个进程都是公平的,让每个进程都运行一段相同的时间片,这就是基于时间片轮询调度算法。
在这里插入图片描述

CFS定义一种新调度模型,它给cfs_rq(cfs的run queue)中的每一个进程都设置一个虚拟时钟-virtual runtime(vruntime)。如果一个进程得以执行,随着执行时间的不断增长,其vruntime也将不断增大,没有得到执行的进程vruntime将保持不变
用进程结构体中下面的属性来表示调度的关系 上面图片中的 具体成员: prio 、 normal prio、static prio、rt priority等。

实际运行时间

CFS是Completely Fair Scheduler简称,完全公平调度器。在实际当中必须会有进程优先级高或者进程优先级低,CFS调度器引入权重,使用权重代表进程的优先级,各个进程按照权重比例分配CPU时间。
假设有2个进程X和Y,X权重为1024,Y权重为2048。
X获得CPU时间比例为: 1024/(1024+2048)=33%左右
Y获得CPU时间比例为: 2048/(1024+2048)-66%左右
在引入权重之后分配给进程的时间计算公式如下:
实际运行时间=调度曲“进程权重/所有进程权重之和。

虚拟运行时间

虚拟运行时间=实际运行时间NICE_ 0_ LOAD/进程权重= (调度周期进程权重/所有进程权重之后)
NICE_ 0_ LOAD/进程权重=调度周期1024/所有进程总权重.
在一个调度周期里面,所有进程的虚拟运行时间是相同的,所以在进程调度时,只需要找到虚拟运行时间
最小的进程调度运行即可

主调度器和周期性调度器

进程调度器任务:合理分配CPU赶时间给运行的进程。调度器目标:有效地分配CPU时间片。
主调度器:通过调用schedule()函数来完成进程的选择和切换。
周期性调度器:根据频率自动调用scheduler tick函数, 作用根据进程运行时间触发调度。
上下文切换:主要做两个事情(切换地址空间、切换寄存器和栈空间)。

左边的cpu和调度器有上下文切换根据
下面有个选择进程 选择进程根据不同的调度类来选择进程 再放到调度器里面进行处理
调度类来判断接下来运行哪个进程
在这里插入图片描述

总结

调度器来分配cpu接下来执行的进程,根据进程的不一样分配不同的调度策略
不同的调度策略影响进程占用的cpu时间片
当有限期进程 直接优先 有实时进程 普通进程差不多只有百分之5的调用空间
当只有普通进程的时候,才开始看看是不是能在cfs下面进行一些公平的调度

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

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

相关文章

【微服务】springboot 通用限流方案设计与实现

目录 一、背景 二、限流概述 2.1 dubbo 服务治理模式 2.1.1 dubbo框架级限流 2.1.2 线程池设置 2.1.3 集成第三方组件 2.2 springcloud 服务治理模式 2.2.1 hystrix 2.2.2 sentinel 2.3 网关层限流 三、常用限流策略 3.1 限流常用的算法 3.1.1 令牌桶算法 3.1.2 …

2023最新Java面试八股文汇总(五十万字总结版)

写在前面 今年的疫情,让招聘面试变得雪上加霜。已经有不少大厂,如腾讯、字节跳动的招聘名额明显减少,面试门槛却一再拔高,如果不用心准备,很可能就被面试官怼得哑口无言,甚至失去了难得的机会。 现如今&a…

<Linux开发>驱动开发 -之- Linux RTC 驱动

<Linux开发>驱动开发 -之- Linux RTC 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细…

Dubbo【 Dubbo概念(什么是分布式系统、什么是RPC、核心组件、Zookeeper注册中心 )】(一)-全面详解(学习总结---从入门到深化)

目录 Dubbo概念_什么是分布式系统 什么是分布式 Dubbo概念_什么是RPC Dubbo概念_简介 Dubbo概念_核心组件 Dubbo配置开发环境_Zookeeper注册中心 Dubbo配置开发环境_管理控制台 Dubbo入门案例_需求介绍 Dubbo入门案例_配置开发环境 Dubbo入门案例_服务生产者配置…

VLC-QT源码编译(Windows10+VS2020+MSVC20019+QT5.15)

参考VLC-Qt的编译与使用 windows10VS2019qt5.15 下载源码 VLC-QT https://github.com/vlc-qt/vlc-qt可以通过git或者直接下载ZIP文件,但是里面的libvlc-header和packaging没有下载下来,需要再自行下载。 VLC https://download.videolan.org/vlc/las…

行为型模式--备忘录模式

目录 概述 结构 案例实现 “白箱”备忘录模式 总结: “黑箱”备忘录模式 优缺点 优点: 缺点: 使用场景 概述 又叫快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这…

zeromq的学习笔记

ctx_t 在创建ctx_t时,会设置以下参数 _io_thread_count io线程数默认是1 _max_sockets最大socket数是1023 _starting标识设置为true,此时socket还没有创建 _terminating设置为false,在调用zmq_ctx_term时该标识会设置为true _tag设置为ZMQ_CTX_TAG_VALUE_GOOD&…

mySql和VSC++

确认主机服务里的mysql服务已打开 使用组合键“winR”运行“services.msc”,进入本地服务窗口; 2.进入本地服务窗口后,在右侧服务列表中,查找到“ mysql ”服务选项; 3.查找到mysql服务选项后,双击打开mysq…

C++ 面向对象(3)——重载运算符和重载函数

C 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。 当您调用一个重…

FDM3D打印系列——3、常用打印材料介绍

大家好,我是阿赵。 FDM3D打印机一般都可以支持多种打印材料的,下面来介绍一下几种常用的打印材料 一、PLA 使用FDM打印,最常见的材料就是PLA了 PLA(Polylactic acid),中文名为生物降解塑料聚乳酸&#…

网络安全面试题,渗透测试面试总结

1.什么是WebShell? WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的─种命令执行环境,也可以将其称做为─种网页后门。黑客在入侵了─个网站后,通常会将这些asp或php后门文件与网站服务器WEB目录下正常的网页文件混在─起,然后就可…

【Vue3】生命周期(钩子)函数

在 Vue 3 中,生命周期函数已经被重新设计为钩子函数,并且与 Vue 2 中的生命周期函数有所不同,可以在 setup 函数中使用 onXXX 形式的钩子函数来执行对应的操作。以下是选项式 API 和组合式 API 中常用的几个钩子函数对比: beforeC…

【Java】PriorityQueue--优先级队列

目录 一、优先级队列 (1)概念 二、优先级队列的模拟实现 (1)堆的概念 (2)堆的存储方式 (3)堆的创建 堆向下调整 (4)堆的插入与删除 堆的插入 堆的…

Kubernetes(k8s)容器编排组件介绍

目录 1 整体架构1.1 Master 架构1.2 Node 架构 2 k8s部署组件介绍2.1 K8s 集群架构图2.2 k8s控制组件2.2.1 控制平面2.2.2 kube-apiserver2.2.3 kube-scheduler2.2.4 kube-controller-manager2.2.5 etcd 2.3 k8s运行组件2.3.1 k8s节点2.3.2 容器集2.3.3 容器运行时引擎2.3.4 ku…

机试复试准备中--梦校真题

一、矩阵转置二、统计单词写法一:读取一整行写法二:依次读入每一个单词 三、二叉排序树(DFS)四、IP地址五、特殊排序六、ab(高精度加法)七、奇偶校验八、最大的两个数九、二叉树遍历(DFS)十、成绩排序十一、…

【C++学习】C++入门 | 引用 | 引用的底层原理 | auto关键字 | 范围for(语法糖)

写在前面: 上一篇文章我介绍了缺省参数和函数重载, 探究了C为什么能够支持函数重载而C语言不能, 这里是传送门,有兴趣可以去看看:http://t.csdn.cn/29ycJ 这篇我们继续来学习C的基础知识。 目录 写在前面&#x…

正交编码与正交沃尔什函数详解

本专栏包含信息论与编码的核心知识,按知识点组织,可作为教学或学习的参考。markdown版本已归档至【Github仓库:https://github.com/timerring/information-theory 】或者公众号【AIShareLab】回复 信息论 获取。 文章目录 正交编码正交编码的…

Spring Boot 集成 WebSocket 实现服务端推送消息到客户端

假设有这样一个场景:服务端的资源经常在更新,客户端需要尽量及时地了解到这些更新发生后展示给用户,如果是 HTTP 1.1,通常会开启 ajax 请求询问服务端是否有更新,通过定时器反复轮询服务端响应的资源是否有更新。 在长…

css基础(二)

目录 1. CSS 的复合选择器 1.1 什么是复合选择器 1.2 后代选择器(重要) 1.3 子选择器(重要) 1.4 并集选择器(重要) 1.5 伪类选择器 1.6 链接伪类选择器 1.7 :focus伪类选择器 1.8 复合选择器总结 二、 CSS 的元素显示模式 2.1什么是元素显示模…

多线程编程和并行计算的实例:期货交易及打车软件算法

多线程编程和并行计算的实例:期货交易及打车软件算法 解决现实生活中的问题时,多处理器和多核系统的普及使并行计算成为一个关键的性能提升手段。在这篇博客中,我们将通过深入讨论两个引人入胜而又具有实际意义的场景——期货交易和打车匹配算法&#xf…