linux操作系统和系统资源理论基础


目录

一:操作系统

二:程序如何被CPU读取

三:CPU缓存

四:CPU缓存策略

五:如何实现系统多任务

六:进程切换过程初探

七:进程的调度规则

八:CPU指令集


 

一:操作系统

        操作系统本质也是一组程序,它是一组接口程序,其作用是提供给用户与计算机交互的接口,不管是windows的图形化桌面,还是linux系统的shell命令行,都是一组用来提供给人类与计算机硬件交互的接口程序而已

内核是什么?

 内核是操作系统的核心,也是操作系统最重要的组成部分,用于管理计算机所有活动并驱动所有硬件。明确来说内核管理操作系统的进程,内存,网络功能,文件系统,硬件的驱动程序等等,因为人类直接操作硬件想要利用硬件资源完成计算的任务是很复杂的,因而内核隐藏了这些复杂性,提供了统一的简洁的接口使得程序开发设计更为简单

而计算机的价值是计算功能,被计算的对象就是为了实现某些功能而编写的代码。在系统上运行的服务是由开发人员编写的代码程序来实现,程序在系统中运行需要解决很多问题,了解了这些问题以及如何解决这些问题,对于进程如何运行以及系统资源的调度就有了一定的理解

 

二:程序如何被CPU读取

   程序是实现某种功能的代码集合体,而运行程序所需的计算能力由CPU提供,因此程序必须要放入CPU中运行。而程序本质也只是由程序员编写的静态的文件,因此它与其它文件一样是保存在硬盘中的。但是CPU的运算速率极高,与磁盘较低的读写速率相差极大,因此无法直接与磁盘进行数据交互。

  因而需要速率更快的中间件作为两者的桥梁,这就是内存,虽然内存的读写速率要比磁盘高很多,但和CPU的运算速率相比还是慢很多,为了能一定程度上弥补两者速率上的差距,CPU引入了缓存机制。

三:CPU缓存

  CPU缓存一般有三级缓存,一级缓存速率近乎接近于CPU速率,成本最高空间小,因此需要有稍大些空间的二级缓存来提供使用,而一级缓存可用来弥补二级缓存与CPU速率上的差距,同理二级缓存用来弥补三级缓存和一级缓存速率的差距,而三级缓存是CPU共享的空间容量也较大,一二级缓存属于CPU独有的,如果CPU是多核的那每颗核心都有自己的一二级缓存。因此在购买PC机时性能体系不止是CPU内存等常规硬件数据,CPU缓存大小也极大影响着计算机性能,通常一级缓存容量多出一倍的计算机通常价格也会高出很多

  一级缓存是CPU处理数据的直接接口,CPU访问到的数据一定是来自一级缓存的,而使用N路关联技术能保障缓存RAM中数据的命中率,同时保障了缓存不会被置换的过于频繁,从此CPU只通过一级缓存读取数据,如果一级缓存中没有数据,就从二级缓存中置换到一级缓存,如果二级缓存也没有,那就从三级缓存中置换,如果三级缓存中没有,就从内存中缓存,这样逐级置换。而读取到缓存中的数据同时会把数据的数据块调入缓存里,此后读取数据直接从缓存里取。大大减少了CPU与R内存直接数据交互概率。而内存其实在本质也属于CPU缓存一种表现形式,只不过它是用来实现CPU与硬盘速率差距的中间层,并且它在速率上仍然不足以弥补差距,因此又需要CPU的三级缓存来弥补

四:CPU缓存策略

  CPU与它的三级缓存也是需要通过一定策略机制来保障CPU读取数据和数据同步的。

有两种:1.回写策略2.通写策略

设想一下:如果当CPU更新了一级缓存中数据,那么需要随即跟新到二级缓存吗,需要随即更新到三级缓存吗?需要随即跟新到内存吗?

  如果不逐级更新的话会如何呢?首先不逐级更新的话系统就无法把CPU更新的数据通过缓存逐级置换保存到内存中,那么就无法通过内存把数据刷新到磁盘中,此时如果断电了,而CPU是没有保存数据场所的,数据将会丢失,因此当CPU更新了一级缓存时同时需要逐级更新至内存中的,这种策略叫做通写策略

  但如果每当缓存中有数据更新后都更新到内存中的话也会导致性能降低的。因此还有一种性能更高的CPU缓存策略叫回写策略:当CPU更新一级缓存数据后,不会立即更新至内存,只有当该数据要从一级缓存中丢弃时才逐级更新至内存中。很显然回写策略比通写策略性能要高,因此现在CPU使用的缓存策略都是回写策略

五:如何实现系统多任务

  程序需要运行,首先得由内存把程序文件从磁盘中读取后,通过三层缓存至CPU中运行。现在操作系统是多任务的,即众多进程可以同时运行。但其实CPU某一时刻只能运行一个进程,但系统上都有大量的进程需要运行,例如单核的CPU同一时间其实只能处理一个进程,如果CPU是八核心的那某一时刻能运行八个进程任务,而系统中进程的数量是远超CPU核心数的,更何况还有很多后台守护进程。但为什么我们日常使用电脑都可以同时运行很多软件呢,看起来就是多任务的呀?因为多任务的实现方式是把CPU的运算能力以时间为单位来进行切割,分给每个进程一个运行时间片,这样CPU在众多的进程中来回切换运行,每个进程只有短暂的毫秒运行时间,时间到了即切换到下一个进程,由于速度极快,因此在我们看来好像是CPU同时运行多个进程的。

六:进程切换过程初探

  那么CPU在如此众多的进程之间切换进行运行肯定是某些机制来保障稳定无差错的,下面来看下具体是如何实现的:

首先1:当一个进程在CPU的某颗核心上运行的时间结束后需要退场,但是这个进程中的指令仍然没有运行结束,还有指令需要继续执行。那就意味着还需要再次调度到CPU上运行,那么该进程下次运行是从哪条指令开始运行呢?

总不能上次运行了一半指令,下次调度到CPU上又得从头开始运行吧?这显示是不合理的。因此需要有一种机制来记录进程的在CPU上的运行状态。

其次2:进程等待下次调度到CPU核心上继续运行,但系统上那么多进程呢?那么是通过何种机制来保障它就一定可以被调度到CPU上运行呢?并且何时被调度到CPU上继续运行呢?

  就以上两个问题我们进一步了解进程的调度过程。首先进程是在CPU上运行的,但进程的管理和调度工作是由内核实现的,为了保证每个进程退场后下次入场能继续沿着上次执行指令的位置继续往下运行,因此在CPU运行过程中CPU需要记录进程的指令执行位置的状态信息,完成此项工作的是CPU的指令指针寄存器,它永远指向下一条指令(比如进程上次执行到了第50条指令时就退出CPU了,下次调度到CPU上必须是从第51条指令继续执行的),而每一次进程被调度到CPU上运行,CPU寄存器就会记录该进程的执行状态信息,那么势必会刷新前面的进程记录在寄存器中的信息的,那么记录的数据就会丢失了。并且CPU是没有存放数据的空间场所的,寄存器只是个临时记录信息的场所。因而当进程退出CPU时就需要把自己的运行位置信息找一个可永久存储的地方,所以内核需要有个永久存储该信息的地方。而这个场所就是内核的内核空间,当进程退出时寄存器就把该状态信息保存到了内核中(这叫做保存现场)。具体位置在内核空间中对应的这个进程的进程描述符结构信息中(内核为了便于管理如此多的进程,在每个进程被创建的时候就会为它们创建一个进程描述符来保持进程的相关信息,下面会具体谈到进程描述符)。

那我们想以一下,当下一个被调度到CPU上运行的进程,它有没有可能是之前已经在CPU上运行过的呢?如果有那么它肯定在寄存器中保留了上次运行的状态信息的,那么是不是需要将进程保存的现场信息进行恢复呢,好让进程能接着上次的进度接着运行。这就是恢复现场的动作,进而保障它继续正常运行。因而进程之间的切换势必会不断的发生保存和恢复现场的动作(这个动作其实远远不止是进程状态位置这一个参数的保存和恢复,后面会详细铺开讲解)。而这个切换也是需要时间的,也会造成CPU资源浪费在进程切换上。事实上内核为了实现进程管理,且为了要能追踪到每个进程的执行状态信息,要明确知道当前系统启动了多少进程,另外需要记录的信息很多:(每个进程执行次序,执行时间,退场时执行位置...)而为了快速且有条理的完成这些工作,每创建一个进程时,内核在内核空间中都会为每个进程创建一个进程描述符(stak structure),这个进程描述符是内核存放进程信息的固定数据结构格式,用来描述进程状态信息的。因此每个进程在内核的内核空间中都有属于自己的数据结构,记录着每个进程的进程名,在内存中占用的页面,运行状态信息等等。有了这些信息内核管理进程变的得心应手。而内核的内核空间是在内存中的,内存空间总体上分为用户空间和内核空间

七:进程的调度规则

    而系统上众多的进程需要被运行,可提供资源的CPU核心数量是有限的,因此也跟我们人类社会一样需要有一定的规则次序来保障有限的公共资源被每个进程相对公平的使用,首先不能让进程乱做一团,得让进程按照一定的规则等待CPU资源。得所有的进程在一个有组织的队列中,每个CPU核心都有一个进程队列,比如8核心的CPU那就有八个这样的队列,所以同一时刻可以允许八个进程同时运行。人类排队一般就是按照队列顺序来进行划分优先级的,而进程调度并不是依靠排队的先后顺序的,那CPU是如何来判断这些进程执行的先后顺序的呢?因此需要有个界定进程的标签来让进程选择。而这个标签就是进程的优先级。优先级分为三类:1.实时优先级2.静态优先级,3.动态优先级

实时优先级的进程一般是跟内核相关的或者重要的进程,需要优先被运行的。因此实时优先级全部高于静态优先级。用数字1-99来表示,数字越大优先级别越高

静态优先级用数字100-139来表示,数字越小优先级越高

而内核在实现进程调度时对这两种不同优先级的调度方式也是不同的。不同优先级会有不同的进程调度器来完成调度策略。

如下几种调度策略:

SCHED_FIFO: 最简单的调度算法,先进先出队列:谁先到谁先运行

SHCED_RR: 轮调,同级别优先级的进程按照时间片进程

SCHED_Other:用来调度用户空间进程的100-139之间的进程

CFS SCHED:完全公平调度器 调度用户空间静态优先级

使用如下命令可查看进程的调度类别:

下图FF就是SCHED_FIFO调度器

TS就是SCHED_Other调度器,因此TS用来调度100-139优先级的进程的

 上图可以看见有些内核线程的优先级是实时的虽然它有PRI值,但是没意义,两个内核线程的实时优先级是99,是最高级别的,因为这两个内核线程极为重要的,而其它很多内核线程也都是以用户空间优先级方式来定义的

class:调度类别

rtprio:实时优先级

pri:进程的优先级

nice:调整静态优先级

而如果有些进程优先级很低排在它前面的进程一直存在那么这个低优先级进程就得不到运行。而为了保障社会的公平性,不会有人被饿死,内核引用了动态优先级来调整,并监控这些优先级,如果某些进程很久都没有被调度到CPU上运行了,内核会在内部临时性的调高进程的优先级,这就叫做动态优先级。根据进程优先级可知一般可能需要被内核动态调整的进程应该是100-139的静态优先级的进程

而为了让用户按需调整进程优先级,给每个进程都分配了nice值,可以通过管理员用户来调整进程的nice值从而调整进程的优先级,nice值与优先级的对应关系如下

nice值:100-139  对应进程的静态优先级: -20-19

而普通用户只能调低进程优先级, 管理员用户可以调低或调高自己的优先级

   再进一步分析:虽然进程优先级可以保障进程有次序的被调度,但是在队列里众多的进程中挑选出下面哪一个进程调度到CPU中也是很复杂的算法。如果内核遍历扫描进程未免效率过低了,并且有很多相同优先级的进程。为了实现快速的调度功能,内核将每个队列按照优先级再次进行内部划分(跟以前学校划分阳光班一样按成绩划分不同等级的班级体),内核将按照进程的139个优先级分为139个队列,每一个优先级别的进程为一个队列,下面只需要扫描每个队列的首部,就知道这个队列里的进程是哪个优先级别的了,按照队列的优先级从高到低,只要优先级高的队列中是有进程的,那就挑选出来调度到CPU上,直到队列扫描为空后再进行次级别的级队列进行扫描。

八:CPU指令集

 了解了内核管理进程的一些原理后,进一步深入具体管理方式,但在这之前先了解下CPU指令

一:CPU指令集分为特权指令和普通指令

   1.特权指令:指的是需要调用硬件资源完成某些工作,是不允许程序自己调用,比如一条mkdir指令创建一个文件。这就需要在硬盘上存数据,涉及到硬件资源调度了,而计算机的所有硬件是统一由内核来管理的。因此这种指令是无法直接由CPU执行完成的。并且任何需要用到特权指令的的功能,都由操作系统把它封装成了一个一个的调用,任何程序不能直接操作,必须先向内核申请系统调用才行,申请调用后由内核来接管进行操作,由用户模式进入内核模式

   2.普通指令:即不需要调用硬件资源,由CPU即可在用户空间中完成

我们把执行用户代码的机制叫做用户空间也叫用户模式,表示整个操作系统运行在用户模式下,而一旦用户模式中的指令发起系统调用,意味着不在执行用户代码,是在执行内核代码,而把执行内核代码的机制叫做内核空间也叫内核模式

由上可见,一个程序中的指令一般都会包含特权指令和普通指令,这也意味着进程执行过程中需要向内核申请调用,因此进程运行过程中往往都是在用户模式和内核模式下来回切换的,而这种切换本身也需要时间消耗资源的。因此如果一个程序在运行过程中大量时间都花费在了内核模式下,显示是不理想的,有生产能力的程序应该大部分时间都在执行用户代码上。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值