计算机(Computer),俗称电脑,是一种能够按照事先存储的程序,自动、高速地进行大量数值运算和各种信息处理的现代化智能电子设备。计算机硬件发展史(From Egon)
计算机系统
一台完整的计算机硬件系统由以下5部分构成:运算器、存储器、控制器、输入设备、输出设备。
运算器:负责算术运算与逻辑运算,与控制器共同组成了中央处理器(CPU)。
存储器:用来存储正在进行程序、将要进行程序的数据及刚处理完的数据。
控制器:负责发送和接收指令。
输入设备:用来进行输入的设备,如键鼠、扫描仪等。
输出设备:用来进行输出的设备,如显示器、音响等。
整个计算机系统由硬件和软件所组成。人们把没有安装任何软件的计算机称为裸机。裸机是不能执行任何计算和处理,必须通过软件系统来使它运行起来。软件也可以理解为程序,程序是通过编程语言完成的,这是人们与计算机进行沟通的重要渠道。软件一般分为系统软件和应用软件。
系统软件是指控制和协调计算机及外部设备,支持应用软件开发和运行的系统,是无需用户干预的各种程序的集合,主要功能是调度,监控和维护计算机系统;负责管理计算机系统中各种独立的硬件,使得它们可以协调工作。系统软件使得计算机使用者和其他软件将计算机当作一个整体而不需要顾及到底层每个硬件是如何工作的。这就为程序员进行应用软件的开发清除了很多障碍。系统软件举例:windows xp 、windows 7、windows 8、windows 10 、Android(安卓手机系统) 、IOS(苹果手机系统),unix,linux等。应用程序是用户利用计算机来解决某些问题所编制的程序,如工程设计程序、数据处理程序、自动控制程序、企业管理程序、情报检索程序、科学计算程序等等。
图1 图2
CPU(Center Processing Unit,集运算及控制)
整个计算机硬件系统中,最重要的当属CPU了,它在整个计算机系统中的作用就相当于我们的大脑。它从内存中取指令->解码->执行,然后再取指令->解码->执行下一条指令,周而复始,直至整个程序被执行完成。因为访问内存以得到指令或数据的时间比cpu执行指令花费的时间要长得多,所以,CPU内部都有一些用来保存关键变量和临时数据的寄存器,这样通常在cpu的指令集中专门提供一些指令,用来将一个字(可以理解为数据)从内存调入寄存器,以及将一个字从寄存器存入内存。cpu其他的指令集可以把来自寄存器、内存的操作数据组合,或者用两者产生一个结果,比如将两个字相加并把结果存在寄存器或内存中。这样再次调用寄存器中的指令就会使等待时间大大缩短。
寄存器的分类:
1.保存变量和临时结果的通用寄存器。
2.多数计算机还有一些对程序员设计的专门寄存器,其中之一便是程序计数器(或称为指令指针),它保存了将要取出的下一条指令的内存地址。在指令取出后,程序计算器就被更新以便执行后期的指令。
3.另外一个寄存器便是堆栈指针,它指向内存中当前栈的顶端。该栈包含已经进入但是还没有退出的每个过程中的一个框架。在一个过程的堆栈框架中保存了有关的输入参数、局部变量以及那些没有保存在寄存器中的临时变量。
4.最后一个非常重要的寄存器就是程序状态字寄存器(Program Status Word,PSW),这个寄存器包含了条码位(由比较指令设置)、CPU优先级、模式(用户态或内核态),以及各种其他控制位。用户通常读入整个PSW,但是只对其中少量的字段写入。在系统调用和I/O中,PSW非常非常非常非常非常非常重要。
除了在嵌入式系统中的非常简单的CPU之外,多数CPU都有两种模式,即内核态与用户态。通常,PSW中有一个二进制位控制这两种模式。
内核态:当cpu在内核态运行时,cpu可以执行指令集中所有的指令,很明显,所有的指令中包含了使用硬件的所有功能。(操作系统在内核态下运行,从而可以访问整个硬件)
用户态:用户程序在用户态下运行,仅仅只能执行cpu整个指令集的一个子集,该子集中不包含操作硬件功能的部分,因此,一般情况下,在用户态中有关I/O和内存保护(操作系统占用的内存是受保护的,不能被别的程序占用),当然,在用户态下,将PSW中的模式设置成内核态也是禁止的。
那为什么需要设计出两种工作模式呢?由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU从而划分出两个权限等级。
所有用户程序都是运行在用户态的,但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据,或者从键盘获取输入等。而唯一可以做这些事情的就是操作系统,所以此时程序就需要向操作系统请求以程序的名义来执行这些操作。
这时需要一个这样的机制: 用户态程序切换到内核态,但是不能控制在内核态中执行的指令,这种机制叫系统调用(system call),在CPU中的实现称之为陷阱指令(Trap Instruction)。
它们的工作流程如下:
- 用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务。
- 用户态程序执行陷阱指令。
- CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问。
- 这些指令称之为陷阱(trap)或者系统调用处理器(system call handler)。他们会读取程序放入内存的数据参数, 并执行程序请求的服务。
- 系统调用完成后,操作系统会重置CPU为用户态并返回系统调用的结果。
多线程和多核芯片
Moore定律指出,芯片中的晶体管数量每18个月翻一倍,随着晶体管数量的增多,更强大的功能成为了可能,如
I.第一步增强:在cpu芯片中加入更大的缓存,一级缓存L1,用和cpu相同的材质制成,cpu访问它没有延时。
II.第二步增强:一个cpu中的处理逻辑增多,intel公司首次提出,称为多线程(multithreading)或超线程(hyperthreading),对用户来说一个有两个线程的cpu就相当于两个cpu。多线程运行cpu保持两个不同的线程状态,可以在纳秒级的时间内来回切换,速度快到你看到的结果是并发的,伪并行的,然而多线程不提供真正的并行处理,一个cpu同一时刻只能处理一个进程(一个进程中至少一个线程,进程是资源单位而线程才是cpu的执行单位)。
III.第三步增强:除了多线程,还出现了包含2个或者4个完整处理器的cpu芯片,如下图。要使用这类多核芯片肯定需要有多处理操作系统。
图3
存储器
由于硬件技术的限制,我们可以制造出容量很小但很快的存储器,也可以制造出容量很大但很慢的存储器,鱼与熊掌不可兼得,不可能制造出访问速度又快容量又大的存储器。因此,现代计算机都把存储器分成若干级,称为Memory Hierarchy,按照离CPU由近到远的顺序依次是CPU寄存器、Cache、内存、硬盘,越靠近CPU的存储器容量越小但访问速度越快,下图给出了各种存储器的容量和访问速度的典型值。
图4
寄存器、Cache和内存中的数据都是掉电丢失的,这称为易失性存储器(Volatile Memory),与之相对的,硬盘是一种非易失性存储器(Non-volatile Memory)。
除了访问寄存器由程序指令直接控制之外,访问其它存储器都不是由指令直接控制的,有些是硬件自动完成的,有些是操作系统配合硬件完成的。
Cache从内存取数据时一次取一个Cache Line缓存起来,操作系统从硬盘取数据时一次取 几KB缓存起来,都是希望这些数据以后会被访问到。大多数程序的行为都具有局部性 (Locality)的特点:它们会花费大量的时间反复执行一小段代码(例如循环),或者反 复访问一个很小的地址范围中的数据(例如访问一个数组)。所以预读缓存的办法是很有 效的:CPU取一条指令,我把它相邻的指令也都缓存起来,CPU很可能马上就会取 到;CPU访问一个数据,我把它相邻的数据也都缓存起来,CPU很可能马上就会访问到。 设想有两台计算机,一台有32KB的Cache,另一台没有Cache,而内存都是512MB的, 硬盘都是100GB的,虽然多出来32KB的Cache和内存、硬盘的容量相比微不足道,但由 于局部性原理,有Cache的计算机明显会快很多。高速存储器即使容量只能做得很小也能 显著提升计算机的性能,这就是Memory Hierarchy的意义所在。
寄存器即L1缓存:
用与cpu相同材质制造,与cpu一样快,因而cpu访问它无延时,典型容量是:在32位cpu中为32*32,在64位cpu中为64*64,在两种情况下容量均<1KB。
高速缓存即L2缓存:
主要由硬件控制高速缓存的存取,内存中有高速缓存行按照0~64字节为行0,64~127为行1……最常用的高速缓存行放置在cpu内部或者非常接近cpu的高速缓存中。当某个程序需要读一个存储字时,高速缓存硬件检查所需要的高速缓存行是否在高速缓存中。如果是,则称为高速缓存命中,缓存满足了请求,就不需要通过总线把访问请求送往主存(内存),这毕竟是慢的。高速缓存的命中通常需要两个时钟周期。高速缓存未命中,就必须访问内存,这需要付出大量的时间代价。由于高速缓存价格昂贵,所以其大小有限,有些机器具有两级甚至三级高速缓存,每一级高速缓存比前一级慢但是容量大。
缓存在计算机科学的许多领域中起着重要的作用,并不仅仅只是RAM(随机存取存储器)的缓存行。只要存在大量的资源可以划分为小的部分,那么这些资源中的某些部分肯定会比其他部分更频繁地得到使用。此时用缓存可以带来性能上的提升。一个典型的例子就是操作系统一直在使用缓存,比如,多数操作系统在内存中保留频繁使用的文件(的一部分),以避免从磁盘中重复地调用这些文件,类似的/root/a/b/c/d/e/f/a.txt的长路径名转换成该文件所在的磁盘地址的结果然后放入缓存,可以避免重复寻找地址,还有一个web页面的url地址转换为网络地址(IP)地址后,这个转换结果也可以缓存起来供将来使用。
缓存是一个好方法,在现代cpu中设计了两个缓存,再看图3中的两种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进制位。
每个磁头可以读取一段环形区域,称为磁道。把一个机械手臂位置上所有的磁道合起来,组成一个柱面。每个磁道划成若干扇区,扇区典型的值是512字节。
数据都存放于一段一段的扇区,即磁道这个圆圈的一小段圆圈,从磁盘读取一段数据需要经历寻道时间和延迟时间。
平均寻道时间:
机械手臂从一个柱面随机移动到相邻的柱面的时间成为寻到时间,找到了磁道就以为着招到了数据所在的那个圈圈,但是还不知道数据具体这个圆圈的具体位置。
平均延迟时间:
机械臂到达正确的磁道之后还必须等待旋转到数据所在的扇区下,这段时间称为延迟时间。
虚拟内存:
许多计算机支持虚拟内存机制,该机制使计算机可以运行大于物理内存的程序,方法是将正在使用的程序放入内存取执行,而暂时不需要执行的程序放到磁盘的某块地方,这块地方称为虚拟内存,在linux中称为swap。这种机制的核心在于快速地映射内存地址,由cpu中的一个部件负责,称为存储器管理单元(Memory Management Unit ,MMU)。
PS:从一个程序切换到另外一个程序,称为上下文切换(context switch),缓存和MMU的出现提升了系统的性能,尤其是上下文切换。
图5
图6
更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2017-05/144224p2.htm
I/O设备
cpu和存储器并不是操作系统唯一需要管理的资源,I/O设备也是非常重要的一环。I/O设备一般包括两个部分:设备控制器和设备本身。
控制器:是查找主板上的一块芯片或一组芯片(硬盘,网卡,声卡等都需要插到一个口上,这个口连的便是控制器),控制器负责控制连接的设备,它从操作系统接收命令,比如读硬盘数据,然后就对硬盘设备发起读请求来读出内容。
控制器的功能:通常情况下对设备的控制是非常复杂和具体的,控制器的任务就是为操作系统屏蔽这些复杂而具体的工作,提供给操作系统一个简单而清晰的接口
设备本身:有相对简单的接口且标准的,这样大家都可以为其编写驱动程序了。要想调用设备,必须根据该接口编写复杂而具体的程序,于是有了控制器提供设备驱动接口给操作系统。必须把设备驱动程序安装到操作系统中。
总线
从概念上讲,一台简单的个人计算机可以抽象为类似图7的模型,CPU、内存以及I/O设备都由一条系统总线(bus)连接起来并通过总线与其他设备通信。但是随着处理器和存储器速度越来越快,单总线很难处理总线的交通流量了,于是出现了图8的多总线模式,他们处理I/O设备及cpu到存储器的速度都更快。
北桥即PCI桥:连接高速设备
南桥即ISA桥:连接慢速设备
图7
图8
启动计算机
在计算机的主板上有一个基本的输入输出程序(Basic Input Output System,BIOS)
BIOS就相当于一个小的操作系统,它有底层的I/O软件,包括读键盘,写屏幕,进行磁盘I/O,该程序存放于一非易失性闪存RAM中。
启动流程:
1.计算机加电。
2.BIOS开始运行,检测硬件:cpu、内存、硬盘等。
3.BIOS读取CMOS存储器中的参数,选择启动设备。
4.从启动设备上读取第一个扇区的内容。(MBR主引导记录512字节,前446为引导信息,后64为分区信息,最后两个为标志位)
5.根据分区信息读入bootloader启动装载模块,启动操作系统。
6.然后操作系统询问BIOS,以获得配置信息。对于每种设备,系统会检查其设备驱动程序是否存在,如果没有,系统则会要求用户安装设备驱动程序。一旦有了全部的设备驱动程序,操作系统就将它们调入内核。然后初始有关的表格(如进程表),创建需要的进程,并在每个终端上启动登录程序或GUI。
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-05/144224.htm