一、操作系统的概念
定义:从本质上来说操作系统就是把底层硬件抽象成了一层虚拟机,所以说计算机本身就是一个虚拟机。计算机本身并不会做任何事情,它就是一堆铁疙瘩,即使给它加电它也不会做任何事情,cpu只有在程序的指挥下才会做事情。所以,操作系统的启动就是一个自举的过程,上电的一刹那间主板上的一块ROM芯片中的代码会被自动映射到内存的低地址空间,这块ROM芯片中存的就是BIOS。
二、核心五大部件
在冯诺依曼体系中,计算机有五大部件,分别是运算器、控制器、寄存器、输入设备和输出设备。其中CPU最核心的是运算器、控制器和寄存器。
运算器:负责算术、逻辑运算等,
控制器:控制指令,包括数据的存取过程。程序就是由指令+数据组成的
寄存器(Register):将取回的数据暂存于此,同时起到中间数据计算结果存放的功能。
因此运算器在控制器的控制下不断从寄存器中读取数据处理,在计算机内部的存储器速度是最快的,称为寄存器(暂存)。之所以称为寄存器是因为里面的数据刷新频率很快可以跟CPU刷新频率同步,接下来比较快的是一级缓存、二级缓存、三级缓存,再到外面就是内存了,从内到外造价越来越低,存取速度越来越慢,容量越来越大。一级缓存又被分为一级指令缓存,一级数据缓存;二级缓存就没有这样区分了。多核CPU,每一核CPU都有自己一级、二级缓存,而三级缓存是共享的。
寄存器固然能存储数据,但是空间太小,不是存储设备的核心部件,因此必须要跟内存设备打交道
内存(RAM):由多个存储单元组成,一个字节为一个存储单元,或者一个cell为一个存储单元。每个cell都有自己的存储地址,以16进制进行编制。
CPU要想存取数据,就需要知道内存中数据的存储地址,必须要具备寻址数据功能。
北桥芯片(NorthBridge):用来处理高速信号。通常处理CPU(处理器)、RAM(内存)、AGP端口或PCI Express和南桥芯片之间的通信。即是CPU电路单元和RAM的存储电路建立关联关系
32位CPU:相当于CPU有32根地址线与内存相连,每根地址线都能传输0和1两个位的信号,即能处理的信息为2^32bits=512Mbyte,32根线总共会决定出2^32次方个位置,每一个位置都是1Byte,这是内存的基本单位,因此最多能支持的内存为2^32Byte=4GB。同理64位CPU,4G*4G相当于40多亿个4G。
CPU完成寻址的线路、数据读取的线路、控制指令线路,如果每个线路都配上32根地址线就变得相当复杂,因此CPU将这些线路进行复用(线路复用),通过控制位来区分哪些是数据读取、哪些上寻址等
PAE(物理地址扩展):Physical Address Extension。在32位(bit)寻址总线的基础上再增加4bit相当于2^36Byte=64G,但是需要操作系统内核支持寻址64G的能力。32位操作系统无论内核是否支持PAE,单个进程的所能使用的地址空间超不过3G,剩下1G映射给内核了。例如MySQL就是单进程多线程运行,在32位操作系统上最多能使用的内存只有2.7G,因此最好使用64位的操作系统安装64位的MySQL。
这里牵扯到一个问题,为什么缓存可以提高速度?是因为程序的局部性原理,就是我们常说的二八法则。一段程序中执行频率最高的代码往往只有20%,80%的代码很少用到,而这20%的代码完成了整个程序80%的功能。我们可以将这20%的代码缓存到cpu一级缓存或者二级缓存中,因为cpu中的cache的速度和cpu的时钟频率最接近,这样就可以提高程序运行的速度,
一般缓存算法设计的思路都是:最近最少使用原则。将最近最少使用的数据从缓存中移除,毕竟缓存的空间是有限的,要是缓存和内存的价格一样,那就没必要设计缓存了。程序的局部性原理分为空间局部性和时间局部性:空间局部性是指一段代码被访问了,那么它周围的代码也极有可能被访问到。时间局部性是指某一时刻一段代码被访问了,那么过一会儿这段代码极有可能被再次访问。
N路关联:PC机一级缓存空间通常为64KB,而内存远远大于一级缓存。但是CPU读取数据一定是来自一级缓存的,一级缓存没有就去二级缓存寻找,找到即替换一级缓存中的,反之一层一层往下找,直到内存中。由于一级缓存与内存差异巨大,CPU命中需要数据的概率极低。RAM中的每个存储单元都可以直接缓存在一级缓存中的每一个位置,这叫直接映射,因此为了提高命中率引入了N路关联技术。原理上将RAM分为几片,同理一级缓存也分为对应的几片,如下图,所谓1路关联(1 way),内存中的00、08、16、24只能缓存在set 0单元上,01、09、17、25只能缓存在set1单元上,如果00已经在set0单元上,此时08想缓存在set0上,就要将00置换掉
2路关联
如下图,00、08可以同时缓存在set0单元上,而16、24想缓存时需要置换前两个
4路关联
如下图,00、08、16、24可以同时缓存在set0单元上,而01、09、17、25想缓存时需要置换前四个
完全关联
通写策略(write-through):在数据更新时,同时写入缓存Cache和后端存储。此模式的优点是操作简单;缺点是因为数据修改需要同时写入存储,数据写入速度较慢。
回写策略(Write-back):在数据更新时只写入缓存Cache。只在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储。此模式的优点是数据写入速度快,因为不需要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的情况,数据将无法找回。
显卡(video card):跟CPU数据交互量上非常大的,也是接在北桥上的,是一个高速总线。
IO设备:除了CPU中的运算器、控制器、寄存器之外的设备都是IO设备,IO设备分为低速IO和高速IO。高速IO通常指的的PCI总线
为了衔接计算机系统中各个速度比cpu慢的设备,早期的主板上集成有北桥芯片和南桥芯片(现在的主板可能已经不是这么设计了),南桥芯片是将各慢速设备汇总起来一起接入北桥芯片,所以桥接芯片说白了就是汇总各外部设备最终完成和cpu的交互。south bridge上接的通常称为ISA总线,早期的PCI总线都是接到南桥上的,接入北桥的称为PCI-E,PCI-E总线的速度比PCI总线的速度要快得多得多。常见的磁盘总线都是PCI格式的,SCSI、IDE、SATA统称为PCI总线,PCI(外部设备互连)只是一种统称。鼠标、键盘是串行接口的,通常U盘是通过PCI总线连接南桥-北桥-CPU进行数据交互的。如果把U盘做成PCI-E接口,线路带宽足够大,而U盘太慢了,此时把N个U盘并行连接当作一个存储盘使用,由一根PCI-E总线连接北桥与CPU进行数据交互,这种称为固态硬盘。现在很多固态硬盘接口都上SATA接口,建议购买PCI-E接口的固态硬盘。那么问题来了,计算机接了这么多的外部设备,cpu如何区分不同的IO设备呢?类比计算机区分和互联网通信的各个进程的方法,计算机区分不同的和外部通信的进程靠的是套接字,也就是ip地址+端口号。这里cpu区分不同IO设备靠的也是端口号,称为IO端口,在一台计算机上IO端口的数目也是65535个。任何一个硬件设备通过IO总线接入计算机的时,它必须一开机就申请注册一批连续的IO端口。
任何一个硬件设备的电路可能跟CPU内部电路不一致,因此每一个外部设备都有控制器、适配器,控制器和适配器是将外部设备的信号转换成连接CPU总线上能理解的信号,相当于翻译官,同时控制外部设备的传输速率、校验等功能。所谓驱动就是指挥控制器芯片与硬件工作的。
轮巡(poll):CPU连接这么多外接设备,是如何区分电信号是来自硬盘、鼠标还是网卡,它每隔几毫秒去轮巡一次,查看这些设备有没有信号传输。
中断(interrupt):因poll效率非常低,因此每个设备发送信号时通知CPU来查看,CPU怎么得知是哪个设备的信号呢?可能你会想到通过IO端口来识别,IO端口是实现数据交互而不是识别信号交互的
中断控制器(Interrupt Controller):CPU外置芯片,接收中断信号。当某个外部设备(例如网卡卡)传来信号,CPU中断当前操作,将此信号接收至内存中。中断控制器上连接着中断线,每根线代表一个设备(不是固定的设备),用来区分外部设备,线路是可以复用的,
直接内存存取(DMA):如果CPU需要处理每个外部设备发来的信号,将会使CPU很繁琐,因此引用DMA来解决这个问题。由CPU在内存中划好某次传输数据所需空间,并授权某根线路给DMA使用。它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。
在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。
在物理内存当中,最低地址那段空间,最容易寻址的那段空间的起始地址就预留给DMA,一般16M,在DMA最前面还有1M使用的空间是留给BIOS。
CPU工作频率比较快,内存工作频率比较慢,当内存传输数据给CPU时,CPU大部分时间上处于空闲状态的,因此CPU与慢设备打交道时,会浪费许多时钟周期。CPU内部有一个时间产生器(晶体振荡器),始终产生着时钟脉冲。如下图CPU已经转了好几个周期才开始与内村打交道。CPU为了协调步伐一致,要规划好多少个周期后与内存交互。一般上在时钟周期的上升沿(即高电平与低电平进行切换时)进行交互。
操作系统:CPU与外部设备交互经常步伐不一致,为了合理利用CPU资源,即衍生出了Monitor(监控器),发展到后来就成为OS(操作系统),再后来操作系统把计算机抽象成虚拟机。
之所以把操作系统称为虚拟机,是因为我们只有一块cpu芯片(可能是多核心的),只有一块内存,鼠标只有一个,键盘只有一个........但是每个进程都想独占这一整套资源。cpu通过时间片轮转的方式将一个cpu芯片虚拟成多个cpu进行,内存的虚拟通过分页机制,将内存切割成一个个固定大小的页面。好了,现在已经把计算机系统中最重要的两个部件运算器和存储器虚拟出来了(其实就是虚拟的cpu和内存),剩下的那些IO设备如何虚拟呢?其实在IO虚拟不需要专门去做,因为当前哪个进程获得了系统使用权,IO设备就交给整个进程。
进程:一个程序有许多功能,但加载程序的部分功能到CPU中执行的实例称为进程,相当于一个独立运行单位。
多个独立进程同时运行,CPU、缓存、内存、IO设备上如何合理的分配资源的?
1、 CPU:将时间切割成各个独立单位,在时间的维度完成切片进而完成CPU虚拟。
2、 缓存:有足够空间可用即不需要做什么,如果没有的话,则要进行保存。但是这个进程还没有执行完,CPU分配的时间已经到下一个进程了,此时就要保存现在这个进程的指令数(CPU内部的指令计数器:寄存器),也就是保存现场,再次回来就要恢复现场
3、 内存:将空间切片,内核预留一部分,依次分给进程1、进程2等等以此类推,如果是这样划分的话,进程随时启动,随时终止,或者有的进程需要的空间大,有的小,划分的空间进程不够用,有的划分得太多,所以得引入内存保护机制。如此只能将内存按固定大小进行切割,例如按4k大小为一个单位(存储槽)进行切割,每个存储槽为一个页框(page frame),每个存储槽存储的数据叫一个页面(page),在页面和页框上加一个页和页框的映射机制,这个映射上面的进程都各自认为自己拥有所有内存。进程空间(指令区+代码区+数据区+bss段+堆+栈)如,指令一个页,代码一个页,数据两个页等,如下图,代码区和栈由控制芯片映射到内存中的某个页框上,并不是连续的页框。站在进程的角度来讲,它所需数据的地址是线性地址,而真正数据上存放在物理地址,因此需要通控制芯片进行查找,如此多的数据,控制芯片是如何快速查找的呢?其实在控制芯片里将两者的对应关系划分成了页目录(一级目录、二级目录、三级目录等)
4、I/O设备:要跟硬件(即I/O设备)打交道必须通过内核,由内核转给进程。
cpu芯片只有一块,在某一时刻,要么是内核进程在上面运行,要么是用户空间进程在上面运行,内核在cpu上运行时称为内核模式,进程在cpu上运行时称为用户模式。而在内存中内核占据的那段内存空间称为内核空间,用户进程占据的空间叫用户空间。用户模式时,进程是不能直接控制硬件的。这是因为在cpu内部,cpu制造商将cpu能运行的指令划分为4层(仅对x86架构而言),ring0,ring1,ring2,ring3,由于历史原因,ring1和ring2并没有使用,linux只用了ring0和ring3。ring0称为内核模式,也称为特权指令模式,可以直接操控硬件,ring3是用户模式,可以执行一般指令。
当一个运行中的进程要打开文件或者操作麦克风,它发现自己没有权限执行特权指令,于是就会发起系统调用,一旦产生系统调用进程就会退出,从用户模式切换到特权模式,称为模式切换。由内核负责将数据装载至物理内存(物理内存为内核与各进程用户都划分了一段自己的空间)先到内核空间中,再转至进程用户空间,然后映射到线性地址上,这个时候内核再唤醒用户进程进行数据交互。如果有多个进程,即进程队列,这里就牵扯到进程的状态了,这里简单介绍几个。就绪状态:就绪是指在所有进程队列中,这个进程所需的所有资源都已经准备好了。没有就绪的称为睡眠状态,而睡眠状态又分为可中断睡眠和不可中断睡眠,区别是:可中断睡眠是指随时可以唤醒的,不可中断睡眠是指内核为它准备的数据还没有准备好,即使唤醒它,它也不能干活。可中断睡眠不是因为资源没有准备好而睡眠,只是一个阶段的活已经干完了,下一阶段的活儿还没来,于是它就去睡觉了,你可以随时叫醒它,所以称可中断睡眠。而不可中断睡眠一般是因为IO而进入睡眠状态的。
原文:https://www.cnblogs.com/huhyoung/p/8972285.html