操作系统内功篇:硬件结构之CPU是如何执行任务的?

news2024/9/25 7:21:24

一 CPU是如何读写数据的?

1.1 CPU架构(组成)

当代CPU一般是多核心的,每个核心都有自己的一个L1和L2Cache,L3Cache是一个CPU所有核心共享的,一个CPU只有一个。L1Cache分为数据缓存和指令缓存。

CPU有三层高速缓存的目的就是将Cache作为CPU和内存间的缓存层,减少CPU访问内存的频率从而提高效率。 CPU从内存读取数据也是先读取到Cache,一次读取是读取一个Cache Line(缓存行)。所以说缓存行是CPU读取数据的最小单位。Cache Line的大小可以在Linux系统中查看和修改,默认是64byte。

所以说我们访问内存时候尽量按照物理内存地址数据的时候,尽量顺序访问,这样就可以命中率高,从而提高效率。

1.2 CPU伪共享问题

先介绍一下什么是伪共享问题?

多线程因为同时读写同一个CacheLine的不同变量时导致失效的现象。

假设现在有一个双核心CPU,这两个CPU核心并行运行两个不同的线程,同时从内存中读取两个不同的数据,分别是类型为 long 的变量 A 和 B,这个两个数据的地址在物理内存上是连续的,如果 Cahce Line 的大小是 64 字节,并且变量 A 在 Cahce Line 的开头位置,那么这两个数据是位于同一个 Cache Line 中,又因为 CPU Line 是 CPU 从内存读取数据到 Cache 的单位,所以这两个数据会被同时读入到了两个 CPU 核心中各自 Cache 中。 如果这两个不同核心的线程分别修改不同的数据,比如 1 号CPU 核心的线程只修改了 变量 A,或 2 号 CPU 核心的线程的线程只修改了变量 B,会发生什么呢? 结合保证多核缓存一致的 MESI 协议,来说明这一整个的过程:

●①.最开始变量 A 和 B 都还不在 Cache 里面,假设 1 号核心绑定了线程 A,2 号核心绑定了线程 B,线程 A 只会读写变量 A,线程 B 只会读写变量 B。

●②1 号核心读取变量 A,由于 CPU 从内存读取数据到 Cache 的单位是 Cache Line,也正好变量 A 和 变量 B 的数据归属于同一个 Cache Line,所以 A 和 B 的数据都会被加载到 Cache,并将此 Cache Line 标记为「独占」状态。

●③接着,2 号核心开始从内存里读取变量 B,同样的也是读取 Cache Line 大小的数据到 Cache 中,此 Cache Line 中的数据也包含了变量 A 和 变量 B,此时 1 号和 2 号核心的 Cache Line 状态变为「共享」状态。

●④1 号核心需要修改变量 A,发现此 Cache Line 的状态是「共享」状态,所以先需要通过总线广播发送消息给 2 号核心,通知 2 号核心把 Cache 中对应的 Cache Line 标记为「已失效」状态,然后 1 号核心对应的 Cache Line 状态变成「已修改」状态,并且修改变量 A。

●⑤之后,2 号核心需要修改变量 B,此时 2 号核心的 Cache 中对应的 Cache Line 是已失效状态,另外由于 1 号核心的 Cache 也有此相同的数据,且状态为「已修改」状态,所以要先把 1 号核心的 Cache 对应的 Cache Line 写回到内存,然后 2 号核心再从内存读取 Cache Line 大小的数据到 Cache 中,最后把变量 B 修改到 2 号核心的 Cache 中,并将状态标记为「已修改」状态。

所以,可以发现如果 1 号和 2 号 CPU 核心这样持续交替的分别修改变量 A 和 B,就会重复 ④ 和 ⑤ 这两个步骤,Cache 并没有起到缓存的效果,虽然变量 A 和 B 之间其实并没有任何的关系,但是因为同时归属于一个 Cache Line ,这个 Cache Line 中的任意数据被修改后,都会相互影响,从而出现 ④ 和 ⑤ 这两个步骤。

1.3 避免伪共享解决方案

所以为了避免出现伪共享的问题就得让数据避免出现在一个Cache Line。 Linux中为了防止出现这种问题是采用了宏定义的方案,定义一个宏来指定变量的对齐方式,确保变量被存储在不同的缓存行中,避免不必要的缓存行竞争。具体不赘述。

常用的解决伪共享问题的方案还有使用缓存行填充和缓存行隔离技术。

二 CPU如何选择线程?

2.1 进程和线程

进程是分配资源的基本单位,也是调度的基本单位。 进程有自己的PCB,线程有自己的TCB,TCB们用链表管理起来被置在PCB中。本质都是一个结构体,存储着一些变量。不过线程的资源都是用的把这个线程创建出来的进程的资源。所以线程又名轻量级进程。没有创建线程的进程,是只有单个执行流的,被称为主线程。主线程可以创建子线程(工作线程)。

2.2 普通任务和实时任务

Linux中,根据调度进程的优先级和响应要求,优先级数值越小,优先级越高。将调度进程分为两类:

●①实时任务:对系统的响应时间要求很高,要求尽快被执行,优先级在0~99。

●②对响应速度没太大的要求,优先级在100~139。

2.3 调度类

调度类通常是指负责任务调度和资源管理的一个类。调度类通常包含了各种方法和属性,用于实现任务的调度、资源的分配以及执行控制。

调度器是计算机系统中的一个重要组件,其作用是协调和管理系统资源的分配,以实现对任务和进程的调度和执行。

Linux为了保证高优先级的进程能够尽早的被执行,于是有了几种调度类:Deadline/Realtime/Fair Deadline和Realtime这两个调度类都是用于实时任务,这两个调度类的策略策略有三种。

Deadline的调度策略是sched_deadline。Deadline的调度器是Deadline调度器。

Realtime的调度策略是sched_fifo和sched_rr。Realtime的调度器是RT调度器。

Fair的调度策略是sched_normal和sched_batch。调度器是CFS调度器。

Deadline和Realtime是用于实时任务,Fair是用于普通任务。

2.4 完全公平调度

我们平日里遇到的基本都是普通任务,对于普通任务来说,公平性最重要,在 Linux 里面,实现了一个基于 CFS 的调度算法,也就是完全公平调度。

●这个算法的理念是想让分配给每个任务的 CPU 时间是一样,于是它为每个任务安排一个虚拟运行时间 vruntime,如果一个任务在运行,其运行的越久,该任务的 vruntime 自然就会越大,而没有被运行的任务,vruntime 是不会变化的。

●那么,在 CFS 算法调度的时候,会优先选择 vruntime 少的任务,以保证每个任务的公平性。

●这就好比,让你把一桶的奶茶平均分到 10杯奶茶杯里,你看着哪杯奶茶少,就多倒一些;哪个多了,就先不倒,这样经过多轮操作,虽然不能保证每杯奶茶完全一样多,但至少是公平的。

●当然,上面提到的例子没有考虑到优先级的问题,虽然是普通任务,但是普通任务之间还是有优先级区分的,所以在计算虚拟运行时间 vruntime 还要考虑普通任务的权重值,注意权重值并不是优先级的值,内核中会有一个 nice 级别与权重值的转换表,nice 级别越低的权重值就越大。所以虚拟运行时间(vruntime)+=实际运行时间*nice_0_load/权重,可以不用管 nice_0_load 是什么,就认为它是一个常量,那么在「同样的实际运行时间」里,高权重任务的 vruntime 比低权重任务的 vruntime 少,你可能会奇怪为什么是少的?你还记得 CFS 调度吗,它是会优先选择 vruntime 少的任务进行调度,所以高权重的任务就会被优先调度了,于是高权重的获得的实际运行时间自然就多了。

2.5 CPU运行队列

一个系统通常都会运行着很多任务(任务就是进程),多任务的数量基本都是远超 CPU 核心数量,因此这时候就需要排队。

事实上,每个 CPU 都有自己的运行队列,用于描述在此 CPU 上所运行的所有进程,其队列包含三个运行队列,Deadline 运行队列 、实时任务运行队列 和 CFS 运行队列 ,优先级Deadline > Realtime > Fair,这意味着 Linux 选择下一个任务执行的时候,会按照此优先级顺序进行选择,也就是说先从 Deadline运行队列里选择任务,然后从 实时任务运行队列里选择任务,最后从 CFS运行队列里选择任务。因此,实时任务总是会比普通任务优先被执行。

2.6 调度优先级

如果我们启动任务的时候,没有特意去指定优先级的话,默认情况下都是普通任务,在Linux系统中,默认情况下,如果没有特意指定任务的优先级,则新创建的任务通常会被视为普通任务。这些普通任务将按照默认的调度策略和调度参数来进行调度。普通任务的调度类是 Fail,由 CFS 调度器来进行管理。CFS 调度器的目的是实现任务运行的公平性,也就是保障每个任务的运行的时间是差不多的。

如果你想让某个普通任务有更多的执行时间,可以调整任务的 nice 值,从而让优先级高一些的任务执行更多时间。nice 的值能设置的范围是 -20~19, 值越低,表明优先级越高,因此 -20 是最高优先级,19 则是最低优先级,默认优先级是 0。nice 值并不是表示优先级,而是表示优先级的修正数值,它与优先级的关系是这样的:priority(new) = priority(old) + nice。内核中,priority 的范围是 0~139,越低,优先级越高,其中前面的 0~99 范围是提供给实时任务使用的,而 nice 值是映射到 100~139,这个范围是提供给普通任务用的,因此 nice 值调整的是普通任务的优先级。

在前面我们提到了,权重值与 nice 值的关系的,nice 值越低,权重值就越大,计算出来的 vruntime 就会越少,由于 CFS 算法调度的时候,就会优先选择 vruntime 少的任务进行执行,所以 nice 值越低,任务的优先级就越高。

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

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

相关文章

基于SSM+Jsp+Mysql的记账管理系统

开发语言:Java框架:ssm技术:JSPJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包…

C# Solidworks二次开发:获取主窗口API和创建新活动窗口API详解

今天要讲的是Solidworks中的两个API。 (1)Frame Method (ISldWorks):获取SOLIDWORKS主框架。 下面是API中给出的例子: public void Main(){ModelDoc2 swModelDoc default(ModelDoc2);Frame swFrame default(Frame);ModelWindow…

jmeter之接口功能自动化

一、接口测试简述 接口:用来连接前端,后端还有移动端的程序模块。由于不同端的工作进度不一样,需要对最开始出来的接口进行接口测试。 接口分类:POST,GET,PUT,DELETE。 POST请求的数据是放在…

战略精进·第1篇:市场洞察的操作要点分享

首发:麦子禾咨询 作者:石头 近期本来没有计划写战略相关主题的,毕竟在3月初,石头定下来的方向是「大客户经营」,也在围绕大客户主题做些积累。 为什么要打乱现有的节奏,原因很简单,近期正在接…

NIO简介以及用NIO实现一个群聊系统

一、BIO的工作原理 传统Io(BIO)的本质就是面向字节流来进行数据传输的 ①:当两个进程之间进行相互通信,我们需要建立一个用于传输数据的管道(输入流、输出流),原来我们传输数据面对的直接就是管道里面一个个字节数据的流动(我们弄了一个 by…

利用Base64加密算法将数据加密解密

1. Base64加密算法 Base64准确来说并不像是一种加密算法,而更像是一种编码标准。 我们知道现在最为流行的编码标准就是ASCLL,它用八个二进制位(一个char的大小)表示了127个字符,任何二进制序列都可以用这127个字符表…

实用工具推荐:适用于 TypeScript 网络爬取的常用爬虫框架与库

随着互联网的迅猛发展,网络爬虫在信息收集、数据分析等领域扮演着重要角色。而在当前的技术环境下,使用TypeScript编写网络爬虫程序成为越来越流行的选择。TypeScript作为JavaScript的超集,通过类型检查和面向对象的特性,提高了代…

武汉星起航电商:跨境创业领航者,一站式服务助您轻松启航

在当今全球化的浪潮中,跨境电商以其独特的优势,成为越来越多创业者的首选。然而,如何在这个竞争激烈的市场中脱颖而出,实现业务的快速增长,却成为摆在创业者面前的一大难题。武汉星起航电子商务有限公司,正…

【go从入门到精通】if else 条件控制

作者简介: 高科,先后在 IBM PlatformComputing从事网格计算,淘米网,网易从事游戏服务器开发,拥有丰富的C,go等语言开发经验,mysql,mongo,redis等数据库,设计模…

面试算法-82-不同路径

题目 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? …

OpenHarmony实战开发-手写板应用开发操作流程

分布式手写板(ArkTS) 介绍 本篇Codelab使用设备管理及分布式键值数据库能力,实现多设备之间手写板应用拉起及同步书写内容的功能。操作流程: 设备连接同一无线网络,安装分布式手写板应用。进入应用,点击…

皓学IT:WEB06_ EL表达式JSTL标签库

一、EL表达式 1.1.特点 是一个由java开发的工具包 用于从特定域对象中读取并写入到响应体开发任务,不能向域对象中写入。 EL工具包自动存在Tomcat的lib中(el-api.jar),开发是可以直接使用,无需其他额外的包。 标准…

亚马逊云科技:企业如何开启生成式AI之旅?

如果要评选最近两年全球科技行业最热门的细分领域,那么生成式AI绝对会以遥遥领先的票数成为当仁不让的冠军。 然而眼见生成式AI发展得如火如荼,越来越多的企业却陷入了深深的焦虑:应该如何开启生成式AI之旅?又该怎样搭建大模型&am…

33-Java服务定位器模式 (Service Locator Pattern)

Java服务定位器模式 实现范例 服务定位器模式(Service Locator Pattern)用于想使用 JNDI 查询定位各种服务的时候考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术在首次请求某个服务时,服务定位器在 JNDI…

网站引入 Prism,使得代码高亮显示,并一键复制代码块

曾几何时,苦恼如何将本地写好的博文,更好的展示读者屏幕前?若只是简简单单的文章,其实还是很好的解决它的!可是,像我们这样写技术文章(有点牵强)的,在文章内容嵌入部分代…

【C++庖丁解牛】二叉搜索树(Binary Search Tree,BST)

🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1. 二叉搜索树概念2. 二叉…

IDEA 下载依赖包源码报错 Cannot download sources Sources not found for:XXX

最近在做一个功能的时候想看一个库的源码,结果源码下不下来,报Cannot download sources Sources not found for:XXX,网上搜了半天,也找不到靠谱的结论 后来想了下,应该是镜像那边出了问题,把镜像一删,源码…

EPO企业生产运营数智化平台助力制造企业迈向智能制造

随着“中国制造2025”和工业4.0的不断推进,越来越多的制造企业准备迈入智能制造和智慧制造领域,实现数智化管理。企业通过搭建EPO企业生产运营平台,结合自身业务现状和数字化需求,从各个业务场景、部门人员、产品组成等方面进行分…

(一)、Doris安装使用(基于Doris 2.0.6)

第 1 章Doris简介 1.1、 Doris 概述 ​ Apache Doris由百度大数据部研发(之前叫百度 Palo,2018年贡献到 Apache 社区后,更名为 Doris),在百度内部,有超过200个产品线在使用,部署机器超过1000台…

国际品牌交期长 雷卯来帮忙

在当今的电子元器件市场中,防静电电子元器件的需求日益增长。无论是通信安防、医疗、消费类电子、照明行业、航空航天还是汽车电子等领域都会使用到防静电产品,使得防静电电子元器件的需求也呈现出爆发式的增长。在这一市场中,雷卯品牌凭借其…