计算机基础 | 2. 计算机硬件组成
计算机基础 | 2. 计算机硬件组成
林海峰计算机硬件组成
计算机硬件有五大部分:控制器、运算器、储存器、输入设备、输出设备
- 控制器:计算机的指挥系统。控制器通过地址访问存储器,从存储器中取出指令,经译码器分析后,根据指令分析结果产生相应的操作控制信号作用于其他部件,使得各部件在控制器控制下有条不紊地协调工作。
- 运算器:实现算术运算和逻辑运算的部件。
- 存储器:是计算机用来存放所有数据和程序的记忆部件。它的基本功能是按指定的地址存(写)入或者取(读)出信息。 计算机中的存储器可分成两大类:一类是内存储器,简称内存或主存;另一类是外存储器(辅助存储器),简称外存或辅存。 存储器由若干个存储单元组成,每个存储单元都有一个地址,计算机通过地址对存储单元进行读写。一个存储器所包含的字节数称为存储容量,单位有B、KB、MB、GB、TB等。
- 输入设备:是向计算机中输入信息(程序、数据、声音、文字、图形、图像等)的设备。常见的输入设备有:键盘、鼠标、图形扫描仪、触摸屏、条形码输入器、光笔等。 外存储器也是一种输入设备。
- 输出设备:主要有显示器、打印机和绘图仪等。外存储器也当作一种输出设备。
控制器+运算器=CPU
CPU、内存(主存储器)以及其他I/O设备都由一条系统总线(bus)连接起来并通过总线与其他设备通信
- cpu是人的大脑,负责控制全身和运算
- 内存是人的记忆,负责临时存储
- 硬盘是人的笔记本,负责永久存储
- 输入设备是耳朵或眼睛或嘴巴,负责接收外部的信息存入内存
- 输出设备是你的脸部(表情)或者屁股,负责经过处理后输出的结果
- 以上所有的设备都通过总线连接,总线相当于人的神经
上课开始,老师讲课,学生听课,老师是程序员,学生是计算机,学生的器官都是计算机各部分组成
1.你通过耳朵接收老师讲的知识->输入
2.通过自己的神经,将接收的数据存入自己的内存/短期记忆(总线、内存)
3.光听不行,你还需要反应/处理老师讲的知识,于是你的大脑/cpu从短期记忆里取出知识/指令,分析知识/指令,然后学习知识/执行指令 (cpu取指、分析、执行)
4.你通过作业或者说话输出你学到的结果
5.你想要永久将知识保存下来,只能拿出一个笔记本,把刚刚学会的知识都写到本子上,这个本子就是硬盘(磁盘)
处理器
通常将运算器和控制器合称为中央处理器(Central Processing Unit,CPU)。其中运算器用来主要负责程序运算与逻辑判断,控制器则主要协调各组件和各单元的工作,所以CPU的工作主要在于管理和运算。可以说计算机的大脑就是CPU,它从内存中取指令->解码->执行,然后再取指->解码->执行下一条指令,周而复始,直至整个程序被执行完成。
既然CPU的重点在于进行运算和判断,那么要被运算与判断的数据是从哪里来的?CPU读取的数据都是从主存储器(内存) 来的!主存储器内的数据则是从输入单元所传输进来!而CPU处理完毕的数据也必须先写回主存储器中,最后数据才从主存储器传输到输出单元。
在超大规模集成电路构成的微型计算机中,往往将CPU制成一块具有特定功能的芯片,称为微处理器,芯片里边有编写好的微指令集,我们在主机上的所有操作或者说任何软件的执行最终都要转化成cpu的指令去执行,如输入输出,阅读,视频,上网等这些都要参考CPU是否内置有相关微指令集才行。如果没有那么CPU无法处理这些操作。不同的CPU指令集不同对应的功能也不同,这就好比不同的人脑,对于大多数人类来说,人脑的结构一样,但是大家的智商都有差别。
CPU历史
微处理器由一片或少数几片大规模集成电路组成的中央处理器。这些电路执行控制部件和算术逻辑部件的功能。微处理器能完成取指令、执行指令,以及与外界存储器和逻辑部件交换信息等操作,是微型计算机的运算控制部分。它可与存储器和外围电路芯片组成微型计算机。
计算机的发展主要表现在其核心部件——微处理器的发展上,每当一款新型的微处理器出现时,就会带动计算机系统的其他部件的相应发展,如计算机体系结构的进一步优化,存储器存取容量的不断增大、存取速度的不断提高,外围设备的不断改进以及新设备的不断出现等。根据微处理器的字长和功能,可将其发展划分为以下几个阶段。
- 第1阶段(1971——1973年)是4位和8位低档微处理器时代,通常称为第1代。
- 第2阶段(1974——1977年)是8位中高档微处理器时代,通常称为第2代。
- 第3阶段(1978——1984年)是16位微处理器时代,通常称为第3代。
- 第4阶段(1985——1992年)是32位微处理器时代,又称为第4代。
- 第5阶段(1993-2005年)是奔腾(pentium)系列微处理器时代,通常称为第5代。
- 第6阶段(2005年至今)是酷睿(core)系列微处理器时代,通常称为第6代。“酷睿”是一款领先节能的新型微架构,设计的出发点是提供卓然出众的性能和能效,提高每瓦特性能,也就是所谓的能效比。处理器逐渐向更多核心,更高并行度发展。典型的代表有英特尔的酷睿系列处理器和AMD的锐龙系列处理器。
若想具体了解CPU历史参见百度百科:
https://baike.baidu.com/item/中央处理器/284033?fr=aladdin&fromid=368184&fromtitle=CPU#10
CPU的分类与指令集
CPU指令集权限
在说用户态与内核态之前,有必要说一下CPU指令集,指令集是CPU实现软件指挥硬件执行的媒介,具体来说每一条汇编语句都对应了一条CPU指令,而非常非常多的 CPU指令在一起,可以组成一个、甚至多个集合,指令的集合叫CPU指令集。
同时为避免指令操作不规范而导致对计算机系统造成损坏,CPU指令集
设置了权限分级。
以 InterCPU为例,Inter把CPU指令集
操作的权限由高到低划为4级:
- ring 0
- ring 1
- ring 2
- ring 3
其中 ring 0
权限最高,可以使用所有CPU指令集
,ring 3
权限最低,仅能使用常规 CPU指令集,不能使用操作硬件资源的 CPU指令集,比如 IO读写、网卡访问、申请内存都不行,Linux系统仅采用ring 0 和 ring 3 这2个权限。
高情商
- ring 0被叫做内核态,完全在操作系统内核中运行,由专门的 内核线程 在 CPU 中执行其任务
- ring 3被叫做用户态,在应用程序中运行,由 用户线程 在 CPU 中执行其任务
低情商
- 执行内核空间的代码,具有ring 0保护级别,有对硬件的所有操作权限,可以执行所有C P U 指令集,访问任意地址的内存,在内核模式下的任何异常都是灾难性的,将会导致整台机器停机
- 在用户模式下,具有ring 3保护级别,代码没有对硬件的直接控制权限,也不能直接访问地址的内存,程序是通过调用系统接口(System Call APIs)来达到访问硬件和内存,在这种保护模式下,即时程序发生崩溃也是可以恢复的,在电脑上大部分程序都是在,用户模式下运行的
我们已经知道CPU内部是含有微指令集的,我们所使用的的软件都要经过CPU内部的微指令集来完成才行。这些指令集的设计主要又被分为两种设计理念,这就是目前世界上常见到的两种主要的CPU种类:分别是精简指令集(RISC)与复杂指令集(CISC)系统。下面我们就来谈谈这两种不同CPU种类的差异!
精简指令集
精简指令集(Reduced Instruction Set Computing,RISC):这种CPU的设计中,微指令集较为精简,每个指令的运行时间都很短,完成的动作也很单纯,指令的执行效能较佳;但是若要做复杂的事情,就要由多个指令来完成。常见的RISC指令集CPU主要例如Sun公司的SPARC系列、IBM公司的Power Architecture(包括PowerPC)系列、与ARM系列等。【注:Sun已经被Oracle收购;】
- SPARC架构的计算机常用于学术领域的大型工作站中,包括银行金融体系的主服务器也都有这类的计算机架构;
- PowerPC架构的应用,如Sony出产的Play Station 3(PS3)使用的就是该架构的Cell处理器。
- ARM是世界上使用范围最广的CPU了,常用的各厂商的手机、PDA、导航系统、网络设备等,几乎都用该架构的CPU。
复杂指令集
复杂指令集(Complex Instruction Set Computer,CISC)与RISC不同,在CISC的微指令集中,每个小指令可以执行一些较低阶的硬件操作,指令数目多而且复杂,每条指令的长度并不相同。因此指令执行较为复杂所以每条指令花费的时间较长,但每条个别指令可以处理的工作较为丰富。常见的CISC微指令集CPU主要有AMD、Intel、VIA等的x86架构的CPU。
一般认为:CPU 硬件直接支持的数学计算公式执行效率最高。就是因为 CPU 指令集中包含这个数学公式,数学计算只需要一条指令就可以执行完毕。反之就需要通过多条 CPU 指令以组合的方式完成数学计算,需要执行多条 CPU 指令,在空间和时间复杂度上都会复杂 N 倍。所以请大家理解 CPU 执行效率高低的来源,当然指令集只是制约 CPU 执行效率高低的其中一个因素,但是该因素绝对是重量级的、起决定性的因素
总结:
CPU按照指令集可以分为精简指令集CPU和复杂指令集CPU两种,区别在于前者的指令集精简,每个指令的运行时间都很短,完成的动作也很单纯,指令的执行效能较佳;但是若要做复杂的事情,就要由多个指令来完成。后者的指令集每个小指令可以执行一些较低阶的硬件操作,指令数目多而且复杂,每条指令的长度并不相同。因为指令执行较为复杂所以每条指令花费的时间较长,但每条个别指令可以处理的工作较为丰富。
x86结构以及64位
x86架构
x86是针对cpu的型号或者说架构的一种统称,详细地讲,最早的那颗Intel发明出来的CPU代号称为8086,后来在8086的基础上又开发出了80285、80386…,因此这种架构的CPU就被统称为x86架构了。
由于AMD、Intel、VIA所开发出来的x86架构CPU被大量使用于个人计算机上面,因此,个人计算机常被称为x86架构的计算机!
程序员开发出的软件最终都要翻译成cpu的指令集才能运行,因此软件的版本必须与cpu的架构契合,举个例子,我们在MySQL官网下载软件MySQL时名字为:
Windows(x86,32-bit),ZIP Archive
(mysql-5.7.20-win32.zip)
我们发现名字中有x86,这其实就是告诉我们:该软件应该运行在x86架构的计算机上。
64位
cpu的位数指的是cpu一次性能从内存中取出多少位二进制指令,64bit指的是一次性能从内存中取出64位二进制指令。
在2003年以前由Intel所开发的x86架构CPU由8位升级到16、32位,后来AMD依此架构修改新一代的CPU为64位,到现在,个人计算机CPU通常都是x86_64的架构。
cpu具有向下兼容性,指的是64位的cpu既可以运行64位的软件,也可以运行32位的软件,而32位的cpu只能运行32位的软件。这其实很好理解,如果把cpu的位数当成是车道的宽,而内存中软件的指令当做是待通行的车辆,宽64的车道每次肯定既可以通行64辆车,也可以通信32辆车,而宽32的车道每次却只能通行32辆车
运算器和控制器
常将运算器和控制器合称为中央处理器(Central Processing Unit,CPU)。
其中运算器用来主要负责程序运算与逻辑判断,控制器则主要协调各组件和各单元的工作,所以CPU的工作主要在于管理和运算。可以说计算机的大脑就是CPU
运算器
运算器是对信息进行处理和运算的部件。经常进行的运算是算术运算和逻辑运算,所以运算器又可称为算术逻辑运算部件(Arithmetic and Logical,ALU)。
运算器的核心是加法器。运算器中还有若干个通用寄存器或累加寄存器,用来暂存操作数并存放运算结果。寄存器的存取速度比存储器的存放速度快很多。
控制器
控制器是整个计算机的指挥中心,它的主要功能是按照人们预先确定的操作步骤,控制整个计算机的各部件有条不紊的自动工作。
控制器从主存中逐条地读取出指令进行分析,根据指令的不同来安排操作顺序,向各部件发出相应的操作信号,控制它们执行指令所规定的任务。控制器中包括一些专用的寄存器。
寄存器
因访问内存以得到指令或数据的时间比cpu执行指令花费的时间要长得多,所以,所有CPU内部都有一些用来保存关键变量和临时数据的寄存器,这样通常在cpu的指令集中专门提供一些指令,用来将一个字(可以理解为数据)从内存调入寄存器,以及将一个字从寄存器存入内存。cpu其他的指令集可以把来自寄存器、内存的操作数据组合,或者用两者产生一个结果,比如将两个字相加并把结果存在寄存器或内存中。
分类
- 除了用来保存变量和临时结果的通用寄存器外
- 多数计算机还有一些对程序员课件的专门寄存器,其中之一便是程序计数器,它保存了将要取出的下一条指令的内存地址。在指令取出后,程序计算器就被更新以便执行后期的指令
- 另外一个寄存器便是堆栈指针,它指向内存中当前栈的顶端。该栈包含已经进入但是还没有退出的每个过程中的一个框架。在一个过程的堆栈框架中保存了有关的输入参数、局部变量以及那些没有保存在寄存器中的临时变量
- 最后 一个非常重要的寄存器就是程序状态字寄存器(Program Status Word,PSW),这个寄存器包含了条码位(由比较指令设置)、CPU优先级、模式(用户态或内核态),以及各种其他控制位。用户通常读入整个PSW,但是只对其中少量的字段写入。在系统调用和I/O中,PSW非常非常非常非常非常非常重要
维护
操作系统必须知晓所有的寄存器。在时间多路复用的CPU中,操作系统会经常中止正在运行的某个程序并启动(或再次启动)另一个程序。每次停止一个运行着的程序时,操作系统必须保存所有的寄存器,这样在稍后该程序被再次运行时,可以把这些寄存器重新装入。
处理器设计的演变
-
最开始取值、解码、执行这三个过程是同时进行的,这意味着任何一个过程完成都需要等待其余两个过程执行完毕,时间浪费
-
后来被设计成了流水线式的设计,即执行指令n时,可以对指令n+1解码,并且可以读取指令n+2,完全是一套流水线。
- 超变量cpu,比流水线更加先进,有多个执行单元,可以同时负责不同的事情,比如看片的同时,听歌,打游戏。
两个或更多的指令被同时取出、解码并装入一个保持缓冲区中,直至它们都执行完毕。只有有一个执行单元空闲,就检查保持缓冲区是否还有可处理的指令
这种设计存在一种缺陷,即程序的指令经常不按照顺序执行,在多数情况下,硬件负责保证这种运算结果与顺序执行的指令时的结果相同。
内核态与用户态
张三是某科技公司的初级Java开发工程师(低权限),目前在15楼办公码代码,公司提供的资源仅有一套电脑(用户态),张三想着这一线的房价,倍感压力山大,于是给自己定下一个目标,一定要做技术总监,在一线扎根, 奋斗B张三,奋斗5年终于当上了技术总监(高权限),之后张三搬到30楼,可以随时向资源部(系统调用)申请公司各种资源与获取公司的机密信息(内核态),所谓是走上人生巅峰。
通过这个故事,我们发现,低权限的资源范围较小,高权限的资源范围更大,所谓的「用户态与内核态只是不同权限的资源范围」。
通关了CPU指令集权限,现在再说用户态与内核态就十分简单了,用户态与内核态的概念就是CPU指令集权限的区别,进程中要读写 I O,必然会用到 ring 0 级别的 CPU指令集,而此时 CPU 的指令集操作权限只有 ring 3,为了可以操作ring 0级别的CPU指令集, CPU切换指令集操作权限级别为 ring 0,CPU再执行相应的ring 0 级别的 CPU 指令集(内核代码),执行的内核代码会使用当前进程的内核栈。
PS:每个进程都有两个栈,分别是用户栈与内核栈,对应用户态与内核态的使用
除了在嵌入式系统中的非常简单的CPU之外,多数CPU都有两种模式,即内核态与用户态。
通常,PSW中有一个二进制位控制这两种模式。
-
内核态:当cpu在内核态运行时,cpu可以执行指令集中所有的指令,很明显,所有的指令中包含了使用硬件的所有功能,(操作系统在内核态下运行,从而可以访问整个硬件)
-
用户态:用户程序在用户态下运行,仅仅只能执行cpu整个指令集的一个子集,该子集中不包含操作硬件功能的部分,因此,一般情况下,在用户态中有关I/O和内存保护(操作系统占用的内存是受保护的,不能被别的程序占用),当然,在用户态下,将PSW中的模式设置成内核态也是禁止的。
用户态与内核态的空间
在内存资源上的使用,操作系统对用户态与内核态也做了限制,每个进程创建都会分配「虚拟空间地址」
,以Linux32位操作系统为例,它的寻址空间范围是 4G(2的32次方),而操作系统会把虚拟控制地址划分为两部分,一部分为内核空间,另一部分为用户空间,高位的 1G(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,而低位的 3G(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用。
- 用户态:只能操作 0-3G 范围的低位虚拟空间地址
- 内核态:0-4G 范围的虚拟空间地址都可以操作,尤其是对 3-4G 范围的高位虚拟空间地址必须由内核态去操作
- 补充:3G-4G 部分大家是共享的(指所有进程的内核态逻辑地址是共享同一块内存地址),是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据
每个进程的 4G 虚拟空间地址,高位 1G 都是一样的,即内核空间。只有剩余的 3G 才归进程自己使用,换句话说就是, 高位 1G 的内核空间是被所有进程共享的!
最后做个小结,我们通过指令集权限区分用户态和内核态,还限制了内存资源的使用,操作系统为用户态与内核态划分了两块内存空间,给它们对应的指令集使用
内核态与用户态切换
用户态下工作的软件不能操作硬件,但是我们的软件比如暴风影音,一定会有操作硬件的需求,比如从磁盘上读一个电影文件,那就必须经历从用户态切换到内核态的过程,为此,用户程序必须使用系统调用(system call),系统调用陷入内核并调用操作系统,TRAP指令把用户态切换成内核态,并启用操作系统从而获得服务。
请把的系统调用看成一个特别的的过程调用指令就可以了,该指令具有从用户态切换到内核态的特别能力。
相信大家都听过这样的话「用户态和内核态切换的开销大」,但是它的开销大在那里呢?简单点来说有下面几点
- 保留用户态现场(上下文、寄存器、用户栈等)
- 复制用户态参数,用户栈切到内核栈,进入内核态
- 额外的检查(因为内核代码对用户不信任)
- 执行内核态代码
- 复制内核态代码执行结果,回到用户态
- 恢复用户态现场(上下文、寄存器、用户栈等)
- 实际上操作系统会比上述的更复杂,这里只是个大概,我们可以发现一次切换经历了「用户态 -> 内核态 -> 用户态」。
用户态要主动切换到内核态,那必须要有入口才行,实际上内核态是提供了统一的入口,下面是Linux整体架构图
从上图我们可以看出来通过系统调用将Linux整个体系分为用户态和内核态,为了使应用程序访问到内核的资源,如CPU、内存、I/O,内核必须提供一组通用的访问接口,这些接口就叫系统调用。
库函数就是屏蔽这些复杂的底层实现细节,减轻程序员的负担,从而更加关注上层的逻辑实现,它对系统调用进行封装,提供简单的基本接口给程序员。
Shell顾名思义,就是外壳的意思,就好像把内核包裹起来的外壳,它是一种特殊的应用程序,俗称命令行。Shell也是可编程的,它有标准的Shell 语法,符合其语法的文本叫Shell脚本,很多人都会用Shell脚本实现一些常用的功能,可以提高工作效率。
最后来说说,什么情况会导致用户态到内核态切换
- 系统调用:用户态进程主动切换到内核态的方式,用户态进程通过系统调用向操作系统申请资源完成工作,例如
fork()
就是一个创建新进程的系统调用,系统调用的机制核心使用了操作系统为用户特别开放的一个中断来实现,如Linux 的 int 80h 中断,也可以称为软中断 - 异常:当 CPU 在执行用户态的进程时,发生了一些没有预知的异常,这时当前运行进程会切换到处理此异常的内核相关进程中,也就是切换到了内核态,如缺页异常
- 中断:当 CPU 在执行用户态的进程时,外围设备完成用户请求的操作后,会向 CPU 发出相应的中断信号,这时 CPU 会暂停执行下一条即将要执行的指令,转到与中断信号对应的处理程序去执行,也就是切换到了内核态。如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后边的操作等。
多线程和多核芯片
moore定律指出,芯片中的晶体管数量每18个月翻一倍,随着晶体管数量的增多,更强大的功能成为了可能,如
- 第一步增强:在cpu芯片中加入更大的缓存,一级缓存L1,用和cpu相同的材质制成,cpu访问它没有时延
- 第二步增强:一个cpu中的处理逻辑增多,intel公司首次提出,称为多线程(multithreading)或超线程(hyperthreading),对用户来说一个有两个线程的cpu就相当于两个cpu,我们后面要学习的进程和线程的知识就起源于这里,==进程是资源单位而线程才是cpu的执行单位==。
多线程运行cpu保持两个不同的线程状态,可以在纳秒级的时间内来回切换,速度快到你看到的结果是并发的,伪并行的,然而多线程不提供真正的并行处理,一个cpu同一时刻只能处理一个进程(一个进程中至少一个线程)
- 第三步增强:除了多线程,还出现了傲寒2个或者4个完整处理器的cpu芯片,如下图。要使用这类多核芯片肯定需要有多处理操作系统
进程
面试都会问什么是进程,什么是线程吧,一般我们对进程的回答是:系统调度资源的最小或基本单位
,怎么理解呢
系统内核中 进程 就是:一段记录专有资源和状态的 task_struct 结构体
,就是一个数据结构或者理解为一个存储资源信息的对象,task_struct 结构体
其存储的信息就是这些:
- 标识符: 与进程相关的唯一标识符,用来区别正在执行的进程和其他进程。
- 状态: 描述进程的状态,因为进程有挂起,阻塞,运行等好几个状态,所以都有个标识符来记录进程的执行状态
- 优先级: 如果有好几个进程正在执行,就涉及到进程被执行的先后顺序的问题,这和进程优先级这个标识符有关
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 程序代码和进程相关数据的指针。
- 上下文数据: 进程执行时处理器的寄存器中的数据。
- IO状态信息: 包括显示的I/O请求,分配给进程的IO设备和被进程使用的文件费宇@极致Linux内核·记账信息:包括处理器的时间总和,记账号等等。
对于 结构体 不理解请看 C 语言语法,很简单,就是 java 中的对象,只不过 结构体 内部只有属性没有方法
这个 task_struct
结构体有个专门的名字:PCB
--> PROCESS control block
,也叫进程控制块,PCB 数据保存在 进程4G内存虚拟地址中的内核态中,也就是 3-4G 内存这一段内,显然用户态时是无法访问的,想要访问就必须从用户态切换到内核态,而且这么核心的数据直接暴露给用户程序也是很危险的
进程在内核中就是这么个东西,就是一个叫 PCB 的 task_struct
结构体,系统内核中有一个 PCB TABLE
用来存储、调度进程
线程
线程在内核中同 进程 一样,也是一个 task_struct
结构体,线程在 new 出来之后就是把 进程的 PCB 复制一份给自己,然后加上 PCB 没有的 PC程序计数器,SP堆栈,State状态,寄存器
这些信息。线程的 task_struct 结构体 叫做:TCB
--> thread control block
。线程本质上就是多了一个任务列表,就是 栈帧
这个东西
大家想 线程为什么能共享堆内存资源呢,怎么做到的呢,真的很简单,把 进程资源信息 PCB 复制一份给 自己的 TCB 就行了,所以这里大家体会下
换个角度理解进程、线程
- 进程 --> 是向系统内核申请资源的最小、基本单位
- 线程 --> 是竞争 CPU 资源的最小、基本单位
==进程
申请的是内存资源,线程
竞争的是 CPU 资源==
内核线程
线程分:内核线程
、用户线程
,内核线程的 TCB 和 进程 的 PCB 保存在一个位置,都是在 3-4G 的内核地址内存中。系统内核中调度的是 内核线程,不是用户线程
内核线程一样有自己的栈帧,所有ring0的代码都淂切换到 内核线程 来执行
用户线程
有了内核线程,为什么还得设计用户线程呢,不用想就是为了和 ring 0
,ring 3
指令权限对应,为的就是权限责任分明。系统内核操作、硬件操作、安全权限高的代码必须得在内核中执行,用户不能碰,用户自己的低权限代码在用户自己的线程中执行就好了,这样设计代码分层,扩展性能好,相互不影响
Linux 中默认采用 1:1 线程模型
,就是有一个 用户线程,就得在内核中启动一个对应的 内核线程,然后把这个 用户线程 绑定到 内核线程 上。当然还有其他的对应方式,这就得依靠第三方实现方案了。C 标准函数库 PThread 线程函数库就是 1:1 线程模型,这点大家想想 Dart 中的线程为啥就能实现资源、内存隔离,肯定就是自己做出修改的
需要说一下 java JVM 采用 Linux 默认函数库,也就是 PThread,1:1 线程模型。java new 一个 Thread 时,是创建了 1个用户线程和内核线程的,然后把用户线程绑定到内线线程中,ring3 的代码在 用户线程中执行,ring0 的代码切换到 内核线程 中去执行,然后使用 内核线程 接受 系统内核的调度,内核线程抢到 CPU 时间片后,用户线程就会激活执行代码
用户线程的 TCB 保存在 进程 0-3G 虚拟地址空间的堆内存中,对于 系统内核 来说是不可见的,所以线程的调度是由 内核线程 来承担、处理
用户线程和内核线程切换
用户线程和内核线程的区别就是 TCB 位置的不同,执行的代码权限级别不同,然后内核线程会接受操作系统内核调度单元的调度指令
那么对于 用户线程和内核线程的切换 怎么理解呢?大家就当做2个线程切换就好了,用户线程和内核线程都有自己的栈帧,寄存器值、CPU 加载的缓存 等属于自己线程的数据,用户线程到内核线程的切换一样会涉及这些 线程上下文 的切换,性能损失在这里
一般来说像 IO 操作这些都是淂在 内核线程 中去执行,所以 IO 代码就会涉及到 用户态到内核态的切换,其中性能损失就是线程上下文的切换,重点是 IO 操作会造成频繁的造成 用户态到内核态再到用户态 的切换。优化的重点是减少切换,所以 mmap 很重要。mmap 实现了不用借助 系统中断,不用到 内核态 执行系统函数,直接往硬盘中读写数据,少了用户态到内核态的切换,所以性能好,效率高
好了就这么多,这么理解就行了,不用想的太复杂,就是这么回事。用户态=用户线程,内核态=内核线程,2者的区别就是对内存操作的范围有区别,对指令的操作权限有区别
存储器
计算机中第二重要的就是存储了,所有人都意淫着存储:
速度快(这样cpu的等待存储器的延迟就降低了)+容量大+价钱便宜。
同时兼备三者是不可能的,所以有了如下的不同的处理方式
存储器系统采用如上图的分层结构,顶层的存储器速度较高,容量较小,与底层的存储器相比每位的成本较高,其差别往往是十亿数量级的
寄存器即L1缓存:
用与cpu相同材质制造,与cpu一样快,因而cpu访问它无时延,典型容量是:在32位cpu中为3232,在64位cpu中为6464,在两种情况下容量均<1KB。
高速缓存即L2缓存:
主要由硬件控制高速缓存的存取,内存中有高速缓存行按照 0~64 字节为行0,64~127为行1。。。最常用的高速缓存行放置在cpu内部或者非常接近cpu的高速缓存中。当某个程序需要读一个存储字时,高速缓存硬件检查所需要的高速缓存行是否在高速缓存中。如果是,则称为高速缓存命中,缓存满足了请求,就不需要通过总线把访问请求送往主存(内存),这毕竟是慢的。高速缓存的命中通常需要两个时钟周期。高速缓存为命中,就必须访问内存,这需要付出大量的时间代价。由于高速缓存价格昂贵,所以其大小有限,有些机器具有两级甚至三级高速缓存,每一级高速缓存比前一级慢但是容易大。
缓存在计算机科学的许多领域中起着重要的作用,并不仅仅只是RAM(随机存取存储器)的缓存行。只要存在大量的资源可以划分为小的部分,那么这些资源中的某些部分肯定会比其他部分更频发地得到使用,此时用缓存可以带来性能上的提升。一个典型的例子就是操作系统一直在使用缓存,比如,多数操作系统在内存中保留频繁使用的文件(的一部分),以避免从磁盘中重复地调用这些文件,类似的/root/a/b/c/d/e/f/a.txt
的长路径名转换成该文件所在的磁盘地址的结果然后放入缓存,可以避免重复寻找地址,还有一个web页面的url地址转换为网络地址(IP)地址后,这个转换结果也可以缓存起来供将来使用。
缓存是一个好方法,在现代cpu中设计了两个缓存,再看4.1中的两种cpu设计图。第一级缓存称为L1总是在CPU中,通常用来将已经解码的指令调入cpu的执行引擎,对那些频繁使用的数据自,多少芯片还会按照第二L1缓存 。。。另外往往设计有二级缓存L2,用来存放近来经常使用的内存字。L1与L2的差别在于对cpu对L1的访问无时间延迟,而对L2的访问则有1-2个时钟周期(即1-2ns)的延迟。
内存:
再往下一层是主存,此乃存储器系统的主力,主存通常称为随机访问存储RAM
,就是我们通常所说的内存,容量一直在不断攀升,所有不能再高速缓存中找到的,都会到主存中找,主存是易失性存储,断电后数据全部消失
除了主存RAM之外,许多计算机已经在使用少量的非易失性随机访问存储如ROM(Read Only Memory,ROM)
,在电源切断之后,非易失性存储的内容并不会丢失,ROM只读存储器在工厂中就被编程完毕,然后再也不能修改。ROM速度快且便宜,在有些计算机中,用于启动计算机的引导加载模块就存放在ROM中,另外一些I/O卡也采用ROM处理底层设备的控制。
EEPROM(Electrically Erasable PROM,电可擦除可编程ROM)
和闪存(flash memory)
也是非易失性的,但是与ROM相反,他们可以擦除和重写。不过重写时花费的时间比写入RAM要多。在便携式电子设备中中,闪存通常作为存储媒介。闪存是数码相机中的胶卷,是便携式音译播放器的磁盘,还应用于固态硬盘。闪存在速度上介于RAM和磁盘之间,但与磁盘不同的是,闪存擦除的次数过多,就被磨损了。
还有一类存储器就是CMOS
,它是易失性的,许多计算机利用CMOS存储器来保持当前时间和日期。CMOS存储器和递增时间的电路由一小块电池驱动,所以,即使计算机没有加电,时间也仍然可以正确地更新,除此之外CMOS还可以保存配置的参数,比如,哪一个是启动磁盘等,之所以采用CMOS是因为它耗电非常少,一块工厂原装电池往往能使用若干年,但是当电池失效时,相关的配置和时间等都将丢失
磁盘
原理
磁盘低速的原因是因为它一种机械装置,在磁盘中有一个或多个金属盘片,它们以5400,7200或10800rpm(RPM =revolutions per minute 每分钟多少转 )的速度旋转。从边缘开始有一个机械臂悬在盘面上,这类似于老式黑胶唱片机上的拾音臂。信息卸载磁盘上的一些列的同心圆上,是一连串的2进制位(称为bit位),为了统计方法,8个bit称为一个字节bytes,1024bytes=1k,1024k=1M,1024M=1G,所以我们平时所说的磁盘容量最终指的就是磁盘能写多少个2进制位。
TB,PB, Eb, Zb, YB
1B= 8bit
1KB=2(10)B=1024B; 括号中的数字为2的指数(即多少次方)
1MB=2(10)KB=1024KB=2(20)B;
1GB=2(10)MB=1024MB=2(30)B。
1TB=2(10) GB=1024GB=2(40)B
1PB=2(10) TB=1024TB=2(50)B
1EB=2(10) PB=1024PB=2(60)B
1ZB=2(10) EB=1024EB=2(70)B
1YB=2(10) ZB=1024ZB=2(80)B1Byte相当于一个英文字母
Kilobyte(KB)=1024B相当於一则短篇故事的内容。
Megabyte(MB)=l024KB相当於一则短篇小说的文字内容。
Gigabyte(GB)=1024MB相当於贝多芬第五乐章交响曲的乐谱内容。
Terabyte(TB)=1024GB相当於一家大型医院中所有的X光图片资讯量。
Petabyte(PB)=l024TB相当於50%的全美学术研究图书馆藏书资讯内容。
Exabyte (EB)=1024PB;5EB相当於至今全世界人类所讲过的话语。
Zettabyte(ZB)=1024EB如同全世界海滩上的沙子数量总和。
Yottabyte(YB)=1024ZB相当於7000位人类体内的微细胞总和。
每个磁头可以读取一段换新区域,称为磁道
把一个戈丁手臂位置上所以的磁道合起来,组成一个柱面
每个磁道划成若干扇区,扇区典型的值是512字节
数据都存放于一段一段的扇区,即磁道这个圆圈的一小段圆圈,从磁盘读取一段数据需要经历寻道时间和延迟时间
平均寻道时间
机械手臂从一个柱面随机移动到相邻的柱面的时间成为寻到时间,找到了磁道就以为着招到了数据所在的那个圈圈,但是还不知道数据具体这个圆圈的具体位置
平均延迟时间
机械臂到达正确的磁道之后还必须等待旋转到数据所在的扇区下,这段时间成为延迟时间
虚拟内存:
许多计算机支持虚拟内存机制,该机制使计算机可以运行大于物理内存的程序,方法是将正在使用的程序放入内存取执行,而暂时不需要执行的程序放到磁盘的某块地方,这块地方成为虚拟内存,在linux中成为swap,这种机制的核心在于快速地映射内存地址,由cpu中的一个部件负责,成为存储器管理单元(Memory Management Unit MMU)
PS:从一个程序切换到另外一个程序,成为上下文切换(context switch),缓存和MMU的出现提升了系统的性能,尤其是上下文切换
磁带
在价钱相同的情况下比硬盘拥有更高的存储容量,虽然速度低于磁盘,但是因其大容量,在地震水灾火灾时可移动性强等特性,常被用来做备份。(常见于大型数据库系统中)
I/O设备(输入输出设备)
cpu和存储器并不是操作系统唯一需要管理的资源,I/O设备也是非常重要的一环。
见四中的图,I/O设备一般包括两个部分:设备控制器和设备本身。
-
控制器:是查找主板上的一块芯片或一组芯片(硬盘,网卡,声卡等都需要插到一个口上,这个口连的便是控制器),控制器负责控制连接的设备,它从操作系统接收命令,比如读硬盘数据,然后就对硬盘设备发起读请求来读出内容。
-
控制器的功能:通常情况下对设备的控制是非常复杂和具体的,控制器的任务就是为操作系统屏蔽这些复杂而具体的工作,提供给操作系统一个简单而清晰的接口
-
设备本身:有相对简单的接口且标准的,这样大家都可以为其编写驱动程序了。要想调用设备,必须根据该接口编写复杂而具体的程序,于是有了控制器提供设备驱动接口给操作系统。必须把设备驱动程序安装到操作系统中。
输入设备
输入设备的任务是把人们编好的程序和原始数据送到计算机中去,并且将他们转换成计算机内存所能识别和接受的信息方式。
安输入信息的形态可分为字符(包括汉字)输入、图形输入、图像输入及语言输入等。目前,常见的输入设备有:键盘、鼠标、扫描仪等。辅助存储器(磁盘、磁带)也可以看作输入设备。另外,自动控制和检测系统中使用的模数(A/D)转换装置也是一种输入设备。
输出设备
输出设备的任务是将计算机的处理结果以人或其他设备所能接受的形式送出计算机。
目前最常用的输出设备是打印机和显示器。辅助存储器也可以看做输出设备。另外,数模(D/A)转换装置也是一种输出设备。
总线
四小节中的结构在小型计算机中沿用了多年,并也用在早期的IBM PC中。但是随着处理器和存储器速度越来越快,单总线很难处理总线的交通流量了,于是出现了下图的多总线模式,他们处理I/O设备及cpu到存储器的速度都更快。
-
北桥即PCI桥
图形与内存控制器
:连接高速设备,负责CPU与内存的数据交换、图形处理、CPU与PCIE数据交换 -
南桥即ISA桥
输入/输出控制器
:连接慢速设备,负责系统的输入输出功能
现在的CPU制造工艺越来越先进,集成度越来越高,内存控制器已被集成到CPU里,就连显卡也被收进CPU了(就是我们所说的核显),而PCIE控制器收归南桥管理了,因此北桥芯片组的功能被瓜分了,所以现在的Intel芯片组把北桥取消掉只剩南桥了,而AMD也只有早期的主板还保留着北桥和南桥。
启动计算机
在计算机的主板上有一个基本的输入输出程序(Basic Input Output system)
BIOS就相当于一个小的操作系统,它有底层的I/O软件,包括读键盘,写屏幕,进行磁盘I/O,该程序存放于一非易失性闪存RAM中。
启动流程
-
计算机加电
-
BIOS开始运行,检测硬件:cpu、内存、硬盘等
-
BIOS读取CMOS存储器中的参数,选择启动设备
-
从启动设备上读取第一个扇区的内容(MBR主引导记录512字节,前446为引导信息,后64为分区信息,最后两个为标志位)
-
根据分区信息读入bootloader启动装载模块,启动操作系统
-
然后操作系统询问BIOS,以获得配置信息。对于每种设备,系统会检查其设备驱动程序是否存在,如果没有,系统则会要求用户按照设备驱动程序。一旦有了全部的设备驱动程序,操作系统就将它们调入内核。然后初始有关的表格(如进程表),穿件需要的进程,并在每个终端上启动登录程序或GUI
引用列表