Linux运维 第二阶段(十六)OS优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux运维 第二阶段(十六)OS优化相关的知识,希望对你有一定的参考价值。

Linux运维 第二阶段(十六)OS优化(1

一、相关概念:

OS optimization

1understanding the linux operating system

CPUcentral processing unit)三大核心部件:运算器、控制器、寄存器

运算器(ALUarithmetic logic unit算术逻辑单元,算术运算、逻辑运算等)

控制器(control unit,控制指令,数据的存取过程,到什么地方加载数据,加载完成后放到什么地方通知运算器计算,计算出的结果如何取出来放到什么地方,由控制指令完成,程序=指令+数据,数据取出来由运算器运算)

寄存器(register,指令寄存器instruction register和程序计数器program counter,数据取出来CPU要在本地完成运算,计算出的中间数据要找一个位置存下来,这就是寄存器要干的事,数据只是暂存很短的时间,而且这个空间是不断被刷新的,只是拿来保存计算的中间结果(运算结果),register固然可实现数据存储,但它并非是核心部件(或核心存储部件),因为它的空间太小了,CPU内部的计数器要具备锁存数据的能力,它的构造结构要比外部的RAMrandom access memory)芯片复杂的多的多,同一个存储单元,若内存RAM中只需一个存储电路,而在CPU寄存器中则需要N个存储电路用来实现暂存,而RAM不具备锁存这种能力,无论读还是写都要与外部的存储建立关联关系)

 

大容量的存储设备就是内存(RAM设备),RAM本身也是一个个的存储单元,通常8bit1byte)为一个单元(一个cell),这些数据最终要能被CPU读取,CPU必须要对应的的找每一个cell,所以CPU在内部要具备寻址数据的能力(到RAM中按地址去寻址数据的能力)

RAM中的每一个cell有自己的存储地址,具有唯一性(按十六进制编址),若CPURAM交互(都是电路单元)中间要通过某一芯片(north bridge)负责将CPU的电路与RAM的存储电路兼容而建立关联关系,RAM上的金手指与主板建立连接并映射到电路上

CPU字长有32bit64bit之分,32bit可理解为CPU出来32根线,这32个电路分为有电和没电两种,这将有2^32=4G个变化,意味着只能找到4G个存储单元,32bitOS只能理解4G的内存空间,64bitOS可理解4G*4G的内存空间(海量)

CPU完成寻址的线路和CPU完成数据存取的线路是同一个线路,线路是复用的,需要一个电路完成控制指令,如用一种标记(000110等)来识别这个线路是如何使用的

 

PAEphysical address extention,给32bit的寻址总线再加4bit,使得最大可寻址内存空间扩展为64GOS要支持这4bit寻址总线的能力,虽有4bit扩展,但并非所有OS都支持寻址这么大,如redhat56就算使用PAE也不支持这么大内存,所以当内存大于4G直接使用64bitOS

若硬件CPU32bit的体系结构OS只能用32bit,若同时使用了PAE技术,无论内存本身是多大,单个进程所能使用的内存空间是不会超过3G的,这只不过使得多个进程总共可使用更多的内存空间,单进程的寻址能力仍是3G,另1G给内核了,这样对单进程的服务来说再大内存也没意义,如mysql是单进程多线程模型,在运行时可能会用更大内存提高更快的速度,而mysql32bitOS上最大只能使用2.7G内存,就算PAE扩至可用64G内存也没意义,这种情况只能使用64bitOS

 

CPU的寄存器与时钟频率几乎是同步的,可与CPU一样的速度完成对数据的存取,而RAM1333MHZ1600MHZ)与CPU的速度是不匹配的,比CPU时钟频率要慢的多,利用缓存可有效提高总体速度,假设的前提是程序具有局部性,空间局部性(某数据被访问到,则认为离它近的数据也会很快被访问到,缓存在加载数据时会将该数据周边的数据一并加载进来,一旦这些数据被访问到则会提高命中率)和时间局部性(一段数据被访问到则认为很快又要被访问到),程序本身很大,缓存器的空间很小比原始程序存放的空间小的多,缓存器比原始存储器要快,缓存器的造价要高,缓存中没有时则到外部的内存中去加载,缓存中通常放内存中的热区数据,根据二八法则放内存中访问最多最频繁的数据,若访问的数据,缓存中没有,当缓存空间未满则补进去即可,当缓存空间已满通过置换策略(MRULRU要好,但要依赖额外的标记位)将之前不用的数据置换出去,若程序在开发时就利用了缓存的原理,那这个程序性能会好很多,那些开发高性能程序的程序员是对计算机原理有着非常精深的理解

CPU引入缓存的机制使得CPU的速度与RAM的巨大差异得到弥补,但又不能最大限度的发挥CPU的性能,所以通常都有多级缓存,一级缓存、二级缓存、三级缓存,一级缓存分一级指令缓存和一级数据缓存,二级缓存用来弥补CPU和三级缓存之间的差异,同理所以,寄存器比一级缓存快,一级比二级快,二级比三级快,三级比内存快,若CPU是多核心的话一级缓存和二级缓存是每核CPU独有的(直接整合在CPU中),三级缓存是共享的,一般缓存离CPU越近造价越高(使用SRAMstatic)静态RAM技术)

CPU若是多核为与内存匹配衔接引入缓存,一级缓存(一级指令缓存I1、一级数据缓存D1)、二级缓存L2、三级缓存L3,其中一级缓存、二级缓存是每核CPU独有的,三级缓存是共享的

RAM是要不断的需要充电,不能有一点供电减小,数据对硬件来说就是有电没电,读一个数据就是将里面的电荷取出来,所以要按某种频率不停的刷新,而SRAM不需要不停的刷写读一次还可再次重复的读,它使用的电路元器件比RAM要复杂的多所以造价要高速度会快的多,CPU的芯片非常小,可操作的空间范围也很小,因此CPU的缓存空间是有限的,一般一级缓存以K为单位(128K,256K等),CPU性能在于主频和缓存能力上(缓存空间翻一倍,价格几乎要翻一倍)

 

RAM的空间(就算热区数据20%)比缓存空间也要大的多的多,而缓存的数据有限,会导致缓存频繁刷新,命中率会很低:

方式一:直接映射,RAM中的每个存储单元都可缓存到缓存空间中的任何位置,这种方式性能低,命中率低

方式二:N路关联技术(1way,2way,4way,8way),8路也称完全关联fully associative,路越多则命中的可能性就高,缓存置换不至于太过频繁

如图:将RAM划分为4片区域00-31,缓存则有8个区域

1way指可存00,08,16,24上其中一个的数据,同一时刻只存这其中的一个,若读到08中的数据,08将覆盖01,同理,使用16上的数据时16会覆盖08

2way指可存00,08,16,2400,08可同时存放到缓存中的第1和第2个区域

4way指可存00,08,16,24上的数据,分别存放在缓存第1234的区域

8way指可存00,08,16,24,01,09,17,25上的数据,分别对应缓存的全部区域

注:00,08,16,24是多个内存单元

技术分享

 

CPU直接打交道的是一级缓存,一级缓存中没有则从二级缓存中转换过来,二级缓存没有则逐级转换,若CPU更新了一级缓存中的数据(写操作),则要随之更新二级-->三级-->内存-->硬盘,对于读只要能命中速度会快的多,要是写操作更新内存相对要慢很多,若不更新万一断电数据就没了,所以要写到内存中

OS内核中有策略会持续不断的将数据从内存写到磁盘上,若没有写入内存的话会导致性能过低,若在写缓存数据时同时更新内存这叫通写write through;若CPU在更新缓存数据后不会立即更新内存,等到缓存中的数据要被丢弃时(需要腾空出来转换其它的数据)才更新,这叫回写write backwrite backwrite through性能要高

现在的CPU对于写操作都是write backCPU要与内存交互大量数据,norith bridge要足够好,通过north bridge这是一种架构,还有一种架构是通过一芯片直接将内存与CPU建驳

RAM外显卡video card通过north bridge也要与CPU交互大量数据,需要CPU处理大量数据,并快速完成交换,数据通过显存带宽(与芯片和CPU交互的通路)交互完成后一帧帧的显示在显示器上,显示的数据需要显存缓存下来,显存不够时还要借助内存来缓存,现在CPU都内置了显存芯片(GPU),独立显卡性能要好点可腾出CPU完成其它工作

注:video card(既要处理大量显存数据,完成硬件加速,又要CPU渲染)

 

技术分享

计算机通常只需要三个核心:运算器、控制器、存储器,与外部交互的其它都称作IO设备,显卡总线就是个IOIO分:高速IO(如PCI-EIO,通常是与north bridge连接)和低速IO(通常与south bridge连接),south bridge将慢速总线的IO设备汇总起来一并接入north bridge,这些桥接芯片汇总外部IO数据总线以完成与CPU的交互;这么多的外围设备最后都通过同一总线(总线是复用的)与CPU交互,为不混淆通过IO port实现

注:PCIperipheral component interconnect外部总线互联,这是统称,有IDESATASCSIUSB等总线)在south bridgePCI-Enorth bridgemousekey是串行速度更慢,

IO port65535个),任何一个硬件设备通过IO总线接入到计算机的总线上,在开机Bios自检时就向CPU申请一批连接的port,每次注册可能都不一样,之后CPU与某一硬件设备交互,CPU就将数据发到已注册的一批连接的port上,硬件设备从这些连接的port上读过来

各种硬件设备内部的电路与计算机内部的电路不总是一致的,所以外部设备都有自己的控制器(或叫适配器),如某一SATA口就是一个控制器(可理解为翻译官,将设备上所能理解的信号转到计算机总线上能通信的信号,控制信号的传输速率、检验等额外功能);驱动通常就是驱动芯片指挥着硬件工作;除内部就有的控制器(mouse,key,disk,usb)之外,有些设备计算机上不会标配,可通过PCI槽(为其它设备预留的空间)接入适配器,这些PCI槽都保留有IO port,没接入适配器时是不需要向CPU注册port

 

所有设备的操作都在CPU的控制下完成,若在键盘上输入数据或网卡上来了数据,如果不响应那电信号就没了,CPU如何知道来了信号:

1pull拉取机制倒简单,但不能用,CPU要在极短的时间不断的向各控制器要数据,CPU同时要处理各种工作,不能在这上面浪费大量时间;

2)通知机制,某个IO设备上来了数据自己要能通过控制器通知到CPU,有很多硬件设备CPU如何知道是谁通知的,通过CPU的中断控制器解决,通常每个硬件设备在启动时要向CPU的中断控制器(CPU外置的芯片,帮CPU识别哪一个硬件设备发送的中断信号)申请使用一个中断向量(有地址的通知机制,硬件设备发的中断信号叫中断向量),中断控制器上有中断线(中断通路,是复用的,可接多个设备),中断控制器在接到信号后会告诉CPU要将当前工作停下先处理紧急的事情,是哪个设备发起的中断请求CPU就通过该设备的IO port与之交互

 

任何外部设备一旦有数据信息,通过中断控制器通知CPUCPU与硬件设备交互把数据读进来,该响应就响应该处理则处理,若某一时刻CPU正忙,将数据读进来的操作这是紧急的,之后的处理过程就不紧急了,CPU该忙其它的就忙其它的去了,等到轮流过来再执行

中断处理过程分为中断的上半部和下半部

上半部(尽可能把中断信号接收下,读到内存中,CPU再去忙其它的事,忙完后再回来处理)

RAM和硬盘比CPU速度要慢的多,CPU要不断的接进来数据同时还要忙其它事情,CPU这样忙也不合理,通过DMA协助完成(可理解为DMA是助理),数据接进来要占据总线,总线是CPU资源(可理解为CPU是领导),若任何硬件都能占据总线并传输数据那CPU就被架空了,所以总线这个资源要被CPU授权后其它设备才能使用,若某硬件设备被授权使用总线,CPU和这个被授权的硬件设备就有竞争了,有竞争就要有锁机制,否则恶意竞争就混乱了,计算机内部若有多颗CPU的话很麻烦,要共享内存等资源,彼此间就有竞争,任何有竞争的地方称作临界区(或关键性区域)

注:硬件设备->south bridge->north bridge->cpu,硬件设备->south bridge->north bridge->RAM

一旦产生中断,CPU接收到中断信号与该设备交互并将数据读进来,发现这个硬件设备有DMA机制,CPU在内存中划分一段连续空间并将总线使用权授权给DMA,于是CPU退出,DMA控制着将数据读到内存中,CPU访问RAM的所有存储单元要有寻址能力(32bit最多能寻址4G的空间),DMA若也有32bit那就相当于是CPU了,所以DMA对内存的寻址能力是很窄的,寻址一小段连续的内存空间,位于内存中低地址的空间预留给DMA使用,并很容易被寻址到的那段起始地址,这段内存空间一般是16M16M下面还有1M空间供BIOS使用;CPU的寻址空间是线性地址空间,并不是直接访问物理内存

计算机开机后本身并不会做其它事情,只有在程序的指挥下才做事,CPU在运行指令后才智能,指令在硬盘,硬盘在哪CPU不知道,CPU有自举的过程,开机后直接把CMOS中的BIOS程序(对硬件做health check)直接映射到线性地址空间的最起始处(内存低地址的那1M区域),CPU去加载该内存区域的指令,开始运行从而进入系统

DMA帮助CPU将数据装载进内存,完成后向CPU发起中断,说明已装载完成,于是CPUDMA待一边去它收回这段总线的使用控制权,负责处理之后的工作,这一切的工作由CPU执行的指令完成,指令来自内存,内存从辅存(硬盘)中获得

 

 

2CPU在某一时刻只运行一个程序,若要运行多个程序,某一时刻CPU从一级指令缓存中取指令,从一级数据缓存中取数据,取一条执行一条,CPU的处理速度要比IO快的多,而程序都是从外部设备加载的,加载后运行,若运行只要1s,而加载过程需要10s9s的时间CPU就要处于等待状态,加载一个执行一个,同时运行的有很多个指令,同时运行的有很多进程,让CPU每时每刻都不闲着,边加载边执行,使得CPU计算资源尽可能利用起来

CPU指挥着硬件同步的协调工作,若CPU100圈,RAM才跑了一圈,各个设备之间要步调一致才行,设备之间交互取决于慢的,为了等待RAM转一圈,CPU就要白转99圈(时钟周期,单位时间内转的圈数),CPU内部有时间产生器(晶体振荡器)产生时钟脉冲,一高一低有波峰有低谷,CPU就以这个时钟脉冲为基准产生时间,大家都以这个时间为准,CPU与这个时钟脉冲同步调,CPU在走完一个周期后而内存可能才走了一点点,CPU与内存的交互一般在时钟周期的上升沿(有上升沿和下降沿,上升沿是从低价到波峰这段,下降沿是波峰到低谷)进行(切换过程)

若只一颗CPU且单核,给我们的假象是多个程序在同时运行,实际上并不是并行,某一时刻仅一个程序中的指令在运行,有一个管理系统负责从硬盘加载一个程序到内存才运行,早期叫monitor(监控程序)-->后来发展越来越大叫OSoperation system-->VMvirtual machine),所有进程要运行都要向OS申请资源(避免某程序独占资源),程序有局部性,每次加载程序的一部分到内存中才执行,这个执行的实体叫processprocess是一个独立的运行单位,这个运行单位又没法直接在硬件上运行,要有OS(或monitor)调度运行,这样可同时有很多运行单位在运行并由OS完成调度,这个独立的运行单位还需要系统资源,如CPU时间、存储空间、运行的结果要保存到内存,因此要实现多个程序独立运行,但CPU、内存只一个如何分配,OS可称作VM,把一个CPU虚拟成多个,把CPU所提供的能力给虚拟出来,按时间进行切片,同时CPU在运行一个进程时还依赖各级缓存,缓存当前程序数据,一旦把CPU时间切出去了,当前使用CPU的权力就在另一进程上了,而另一程序也要使用缓存,若缓存空间足够用倒好,若没有足够的空间之前上个程序缓存的数据就都没了,进程中有很多指令组成,若指令没运行完但分给它的时间到了,如这个进程中有100条指令已执行到第73条,下一次回来运行时就要从第74条开始,CPU通过内部register的程序计数器就知道下次运行第多少条指令,程序计数器始终指向下一条指令的位置(如当正在运行第72条指令时,程序计数器就指向第73条指令),程序切换要保存现场(在内存中保存)、恢复现场,恢复现场时若缓存中没有,数据再加载即可,寄存器中的状态数据一定要能够恢复

 

内存如何虚拟?不能让某一进程直接使用内存,某个进程会认为它没使用的内存空间都是自己的可用空间,这些它认为空闲的内存空间很有可能被其它进程在使用,若这时某一进程直接使用会导致系统崩溃的,让多个进程同时使用,彼此间又不会挤占:

1)按内存空间切片,先给内核预留一部分,再将其它的所有空间分给进程,进程随时会启动或终止,过段时间发现内存中漏洞(碎片)很多,通过这种机制分配,若进程所需的空间不够用时,并不能避免覆盖并占用其它进程的内存空间,要引入内存保护机制,分给某进程多少内存空间它就使用多少,这时不够用时就无法解决了(32bitOSCPU可寻址内存4G空间),因为每个用户的计算机配置不同、程序员开发时并不知道要运行这个程序的主机有多大内存等,这种机制不符合CPU的寻址能力

2)将内存事先划分好固定的存储单元或叫存储槽或叫页框page frame4K为一个单位,byte太小分配回收太复杂使用K为单位),每个page frame存储的一个数据叫一个页面page,引入内存空间的映射机制,每个进程都认为自己有4G的内存空间可用,进程认为的这个空间是模拟出的线性地址是虚拟地址(或叫进程描述结构,该结构由内核在内存中负责维护),通过控制芯片将线性地址映射为内存的物理地址(将每个进程的页数据映射到物理内存的页框);例如一个进程的线性地址中指令区、数据区、BSS区、堆区、栈区各占1个页,共占5个页的数据,通过控制芯片在物理内存中找5个空闲的页框来存这5个区的数据,而且在物理内存中很有可能是不连续的页框;进程在启动时由内核告诉进程你的结构是这样的,真正的数据是在物理内存不连续的页框中,在线性地址中看是规整的但在物理内存上是不规整的;进程在CPU上运行,CPU从内存中取出指令运行,指令要加载页中的某个数据,页的地址是虚拟的线性地址与物理地址并不是一一对应的,CPU在取线性地址中的数据时要通过控制芯片将线性地址翻译为物理地址才能真正拿到数据,这个芯片要保存每个进程线性地址与物理地址的映射关系(通过页目录,一级目录、二级目录、三级目录,目录是映射而不是容器)

 

OSVM):

CPU(按时间切片,各级缓存(缓存当前程序数据),进程切换(保存现场、恢复现场))

内存(线性地址<--物理地址,通过空间映射完成,引入控制芯片还能起到保护内存的能力,芯片在翻译时发现空间不允许访问就访问不了,免得多进程间覆盖使用地址空间)

OS上最主要的虚拟就是CPURAM了,另外还有IO设备(disk,key,mouse,networkcard等)

 

3、若只有一个进程运行时IO设备就不需要虚拟了,谁要获得CPU的使用权通过中断CPU就给谁用了,谁有CPU的使用权焦点就在谁身上,CPU完成了切换IO就完成了切换

若在当前OS上又安装使用了虚拟机,问题就复杂了,CPU已切好片能让多个进程运行,在进程上又装了虚拟机(虚拟机上的OS运行时表现在前主机上就是个进程,除这个进程外当前主机还有其它进程),虚拟机上的CPU又有自己的管理机制,虚拟机的OS上运行的多个进程在管理时如中断、内存管理、CPU管理等都要由当前虚拟机完成管理,给这个虚拟机的CPU本来就是当前主机的OS虚拟出来的,虚拟机内部的多个进程切换时当前主机并不知道切换了没有

OS的内核必须要按CPU走过的时间来计时,虚拟机的内核获得CPU的时间不是完整的时间,它被调度过一次,但它认为它获得的时间是完整的时间,X86的机器设计就是运行一个OS的,而不适合在OS上再运行一个虚拟机(早期X86的架构是不适合运行虚拟机的),不过现在CPU支持硬件虚拟化,有这样的机制才能再次虚拟化,在当前主机OS上的进程的这个层次是已被虚拟过一次了,IO虚拟不需要专门去做,谁获得在CPU上运行通过中断就给那个进程,IO设备都是硬件设备,而真正的硬件控制只有内核才能实现,一旦有IO中断产生有IO交互一定由内核操作,再由内核转给进程

 

当前CPU只一个,要运行一个内核和多个进程,某时刻要么内核在CPU上运行,要么是某个进程在CPU上运行,只会是其中的一种情况,当内核在CPU上运行时叫内核模式,当进程在CPU上运行时叫用户模式;在内存中内核占据的空间叫内核空间,进程占用的空间叫用户空间

CPU有两种模式(内核模式和用户模式,区别在于,用户是不能直接控制硬件的)

CPU权限在CPU内部将指令划分为4层,ring0ring1ring2ring3ring0-3,环0到环3),最核心的ring0叫特权指令模式(内核模式),ring1ring2基于历史原因在现有的OS上没有用,linux上只用了ring0ring3ring3即用户模式,内核运行时能执行特权指令,而用户的进程只能运行的ring3用户模式上

若在OS上运行了虚拟机,这个虚拟机有自己的内核,这个内核若在ring3上则不能执行特权指令(不能将内部的用户程序执行并获取特定的外部资源),不在ring0上运行就不能向内部的用户进程申请资源,让虚拟机运行在限制模式下或使用特殊机制给虚拟机模拟出一层硬件,模拟emulation是仿真,通过软件模拟,让虚拟机上的OS认为这就是个真正的硬件,当要用到特权指令时,由当前主机的OS翻译到硬件上,虚拟机上的OS认为是运行在ring0上事实上是在ring3上运行的,这种虚拟化是完全虚拟化,虚拟机上的OS也能执行特权指令,最终要由真正主机上的OS内核审核才行,虚拟机内部执行的所有指令都要由当前主机的内核翻译,这样把一个计算机的指令用软件模拟,模拟完成后又要由内核翻译才执行,这会非常慢,虚拟机性能能有当前主机性能的六七成就不错了

若能将虚拟机直接运行在ring0上性能就会好很多,将一些敏感的指令不让虚拟机执行,但可让虚拟机直接运行在硬件上,给CPU再加一环(负1环)ring-1-1环由当前主机的内核来运行,虚拟机运行在ring0上,ring0上重要的部分特权指令已剥离,若虚拟机要运行重要的一些特权指令向当前主机的内核申请,硬件虚拟化重要的一点就是提供了ring-1,还有其它额外的机制

 

某一进程在CPU上运行,需要访问资源,资源在内存中,通过线性地址到物理地址映射,程序运行具有局部性,装载这个程序运行时可能只装载了一部分数据,但现在某个进程要额外加载一个文件,文件在辅存上,这就要与硬盘打交道,需要执行特权指令,向内核申请发起系统调用system call,一旦有system call进程就从CPU退出转为内核在CPU上运行(模式切换,用户模式-->内核模式),由内核负责将数据装载进物理内存再映射到进程地址空间(线性地址上),进程通过线性地址就能访问到内存物理地址空间中的数据,内核会为每一段IO准备缓冲区buffer,数据先从磁盘复制到内核的内存空间再复制到进程的地址空间,一旦到进程的内存空间映射关系就建立起来了,进程的请求就已满足,内核唤醒进程,内核退出,进程在CPU上执行后续的工作,OS上总是有多个进程在运行,有可能内核准备好数据了却发现轮不到这个进程运行了,要在进程队列中选一个进程来运行,选哪一个进程运行,ready状态的进程是随时可运行的进程(数据已准备好了),还有睡眠态进程sleelp分可中断睡眠interruptible sleelp(一个阶段的工作已结束下个阶段的工作还没来)和不可中断进程uninterruptible sleelp(内核正在准备数据还没加载完就算唤醒也不能正常工作)

使用公平的方法让进程能被轮流的在CPU上执行,进程有优先级,紧急的事件或关键性任务要先占用CPU运行,优先级高的被调度到CPU上执行的可能性就高且有长时间使用CPU时间的能力,进程除优先级还有先后次序,要有一种设计精良的算法(内核调度进程的算法用时间复杂度衡量)从进程队列中选择一个进程到CPU上运行,算法有标准衡量,符合O1)的算法就是优良(队列无论多长挑选花费的时间是固定的),若队列越长挑选的速度越慢则认为这个算法很差,2.6以上的kernel算法都是O1)的(需要适合的机制(按优先级)将进程排队)

如图:进程运行位置在Applications

技术分享

linuxOS内核上,进程是通过双向链表来管理,表之间有次序,通过一个可找到下一个,进程间是靠一个独立的结构来管理,这个结构叫task_struct(由C语言描述的独立组织的数据结构),其中一个单个的结构也称进程描述符process descriptor,每个进程都有process descriptor,里面存的是进程的元数据(类似文件的元数据),每个进程的描述符间有关联性,在内核内部通过双向链表进行组织,在创建一个进程时首先就创建一个process descriptor并将其添加到此链表上,删除一个进程,process descriptor要被删掉,之后内核将不能追踪这个进程,创建一个进程除要给进程分配CPU、内存等资源外,还要在内核的内存空间中维护一个进程描述符文件,里面保存的有这个进程的所有相关信息,如图:

技术分享

stateready,stopped,sleep(interruptible sleep,uninterruptible sleep),running,zombile

现在的OS都是多任务多用户,多任务是在有限的CPU上超负荷运行多个进程,因此进程切换(CScontext switch上下文切换)不可避免,如CPU上进程A切至进程B,进程A将挂起suspend,各种在CPU内部维持的信息stack pointer,other registers都必须要保存下来(保存现场),保存在process descriptor中,process descriptor的文件大小是固定的,进程A切出去,进程B要调度上来(恢复现场)resume运行,将Bstack pointer,other registers等相关数据要装载到CPU并运行,一旦恢复则程序计数器将指向下一条指令,下一条指令将被装载并执行

技术分享

CS由内核完成,也要花费时间,每次CS都要从用户模式转为-->内核模式再到-->用户模式,整体上CPU就分为两个时间,用户模式所占据的CPU时间和内核模式所占据的CPU时间,可使用top命令查看第三行显示,%us%sy,如:

Cpu(s): 0.0%us0.0%sy, 0.0%ni,100.0%id,  0.0%wa,  0.0%hi, 0.0%si,  0.0%st

正常情况下,内核模式不应占据过多的CPU时间,如web server的工作主要由web进程来完成,如果大量的时间耗费在内核模式下,很有可能CS、中断次数过多导致,对外提供的服务主要是用户空间提供的,这样在响应用户的请求会很慢,影响用户体验等

CS时间太短、太长都不好

linux支持进程抢占,如给进程A运行5msA刚上来没多久就来了进程BB的优先级比A高,B可把A挤下去,优先级高的可抢占CPU,若刚上来就被优先级高的其它进程抢占了这不合理,如果要是等A运行完了再抢那就不是抢了,并不是随时都能抢,而要根据内核内部的时钟频率产生的时钟中断来抢,每次的tick就有可抢的时钟中断,tick来了就能抢,如A进程可在CPU上运行5msOS的内核是100HZ,也就是10ms一次滴答,A可从容的运行完,若内核是1000HZ1ms一次滴答,则A刚上来1ms就被B抢占了,剩下的4ms等下次轮到时再上来运行,这会有问题,优先级高的始终在运行,优先级低的就饿死了

注:时钟频率(clock tick,时钟滴答,1s内的时间跨度,100HZ1s内滴答100次,也就是10ms滴答一次;1000HZ1ms滴答一次),1stick几次叫时间解析度,解析度越高tick越精准,优先级高的进程可抢占的机会也就越多,OS就是根据tick的次数来计算时钟的,如100HZtick100次就认为走了1slinux有两种时钟(硬件时钟;系统时钟),系统时钟就是靠tick实现

CPU足够快,clock tick的频率高无所谓,经验证clock tick快了性能未必好,redhat早期使用100HZ,后调为1000HZ发现不行又改回了100HZredhat6.4已实现了完全无tick的内核,tick less,若要进行tick的话,按100HZ计算,每秒100次的时钟中断必须要进行无论程序有无在运行,若在非常空闲的应用程序当中依然非常消耗电源,更重要的是有大量的时钟中断在进行(空载),引入的stick less可让system进入深度睡眠,要完全靠中断驱动interrupt driven实现(软中断(soft IRQ从用户模型切至内核模式)和硬中断),这样在系统非常空闲的情况下可节约电源不至于让CPU发热量过高等

 

linux进程类别class

交互式进程(通常是IO密集型的,例如编辑器大多数时间都用在等待IO上了)

批处理进程(通常是CPU密集型的,如守护进程,不需与管理员交互,有用户通过网络IO进来它就要响应)

实时进程(随时运行都要能够运行,如导弹中的程序)

 

分配策略:

时间片短,优先级高;

时间片长,优先级低

 

linux优先级prority(调度就是根据优先级来的,实时优先级要比静态优先级要高):

实时优先级(1-99,数字越小,优先级越低,通常与内核相关或关键性任务相关)

静态优先级(100-139,数字越小,优先级越高,通常描述用户空间的优先级)

 

#top(第6行中,PR列中的RT表示实时优先级realtime20表示120NI表示nice value

  PIDUSER      PR  Linux都会学到哪些东西?运维呢?

多线程自动化运维linux的尝试 优化一

多线程自动化运维linux的尝试 优化一

linux运维的发展方向

linux 运维工程师发展路线

[Linux|DBA]运维三十六计