操作系统
引言
不管是程序员还是架构师,基础知识往往是最容易被大家所忽略的,然后每个人的职业生涯的瓶颈取决于个人的基础功力的高低。
其实很多概念对读者来说,并不简单,甚至很多人都并不知道。
为什么要有操作系统
现代的计算机系统主要是有cpu,内存,硬盘,键盘,鼠标,显示器,打印机,网络接口及其他输入输出设备所组成
作为程序员,工作就是编程开发,而编程的本质就是让这些硬件机械去执行我们的指令,代替我们去工作。
所以程员序要掌握所有硬件的物理特性,然后在为期编写管理和控制指令,然后不断优化到能够正常使用每个硬件。但是这样严重影响了程序员的开发效率,想要全部实现根本不现实。
程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱出来,只需要考虑自己的应用软件来编写程序就可以了。应用软件直接使用操作系统提供的功能来间接使用硬件。
什么是操作系统
说了这么多,那么什么是操作系统呢?精简的说:操作系统就是一个协调、管理和控制计算机硬件资源和软件资源的控制程序
细说的话,操作系统应该分成两个部分:
一、隐藏了丑陋的硬件调用接口,为应用程序员提供了调用资源的更好,更简单,更清晰的模型(系统调用接口)。应用程序员有了这些接口后,就不用在考虑操作系统硬件的细节,开发效率大大提高
二、将应用程序对硬件资源的竞太请求变得有序化,比如:很多应用软件其实是共享一套计算机硬件,比方说有三个应用程序同时需要申请打印机来输出内容,那么A程序竞争到了打印机资源就打印,然后可能是B竞争到打印机资源,也可能是C,这就导致了无序,打印机可能打印一段A的内容后又去打印C...。操作系统的一个功能就是将这种无序变得有序(多路复用)
应用程序调用系统接口来间接操作硬件资源,需要注意的是:操作系统的用户就是应用程序或者应用程序开发人员,而应用程序的用户就是计算机的使用者。平时我们熟悉的shell或者GUI (图形用户界面Graphical User Interface)都只是运行于操作系统之上的引用软件,他们并不属于操作系统。
操作系统与普通软件(用户态)的区别是
1.主要的区别是:你不想用快播看小电影了,你可以选择影音先锋或者干脆自己写一个,但是你无法写一个属于操作系统一部分的程序(时钟中断处理程序),操作系统由硬件保护,不能被用户修改。
2.操作系统与用户程序的差异不在于二者所处的地位。特别地说,操作系统是一个大型、复杂、长寿的软件,
大型:linux或者Windows的源代码有五百万行数量级。按照每页50行共1000页的书来算,五百万行要有100卷,要用一整个书架子来摆置,这仅仅还是内核部分。用户程序,如GUI,库以及基本应用软件(如Windows Explorer等),很容易就能达到这个数量的10倍乃至更多。
长寿:操作系统很难编写,如此大的代码量,一旦完成,操作系统所有者便不会轻易扔掉,再写一个。而是在原有的基础上进行更改。(基本上可以吧Windows95/Windows98/Me看出一个操作系统,而WindowsNT/2000/XP/Vista则是两位一个操作系统,对用户来说他们十分相似。还有Unix以及他的变体和克隆版本也演化了多年,如System V版,Solaris以及FreeBSD等都是Unix的原始版,不过尽管linux非常依照Unix模式而仿制,并且与Unix高度兼容,但是Linux具有全新的代码基础)
操作系统的位置
操作系统位于计算机硬件与软件之间,本质上也是一个软件
操作系统发展史
第一代计算机(1940~1955):真空管和穿孔卡片
第一代计算机产生背景:
第一代之前人类是想用机器取代人力,第一代计算机的产生是计算机由机械时代进入电子时代的标志
特点:
没有操作系统的概念
所有程序设计都是由纯粹的机器语言编写
工作过程
程序员在墙上的时钟表预约一段时间,然后程序员拿着他的插件版到机房里,这几个时间内他独享整个计算机资源,后面有一批人在等着
后来出现了穿孔卡片,可以将程序写到卡片上,然后读入计算机而不用插板机
优点
程序员在申请的时间段内独享整个资源,及时调试自己的程序,如果有bug可以及时处理
缺点
这对于计算机提供商来说是一种浪费
严重浪费计算机资源
注意:同一时刻只能有一个程序在内存中,被cpu调用执行,比方说有10个程序的执行,是串行的
第二代计算机(1955~1965):晶体管和批处理系统
第二代计算机生产背景:
由于当时计算机非常昂贵,为了处理一代计算机的浪费计算机资源的缺点,出现了批处理
特点
有了操作系统的概念FORTRAN,这些机器现在被称之为大型机
工作过程
早期的批处理系统:1.程序员将卡片拿到IBM1401机处;
2.1401机将批处理作业读到磁带上;
3.操作员将 输入带 送至IBM7904机;
4.7904机进行计算;
5.操作员将 输出带 送到1401机;
6.1401机打印输出
现代操作系统前身
在收集了大约一个小时的批处理作业之后,这些卡片被读进磁带,然后磁带被送入机房里并装到磁带机上,随后,操作员装入一个特殊的程序(现代操作系统前身),它从磁带上读入第一个作业并不运行,其输出写到第二盘磁带上,而不打印。每个作业结束后,操作系统自动的从磁盘上读取下一个作业并运行,当一批作业完全结束后,操作员取下输入和输出磁带,将输入磁带换成下一批作业,并把输出磁带拿到一台A机上进行脱机(不与主计算机联机)打印。
第一代计算机问题
人机交互太多了(即:输入—>计算—>输出)
二代如何解决一代问题:
1.把一堆人的输入赞成一大波输入
2.把一堆人的输出赞成一大波输出
3.然后顺序计算(二代并没有完全解决)
优点:
批处理,节省时间
缺点:
1.整个过程需要人参与控制,将磁带来回搬来搬去
2.计算过程仍是顺序计算
3.程序员原来独享一段时间的计算机,现在被统一规划到一批作业中,等待结果和重新调试的过程都需要等同批次的其它程序都运行完才可以
第三代计算机(1965~1980):集成电路芯片和多道程序设计
第三代产生背景:
20世纪60年代初期,大多数计算机厂商都有两条完全不兼容的生产线
一条是面向字的:大型的科学计算机,如IBM 7094 主要用于科学计算和科学工程
另一条是面向字符的:商用计算机,如IBM 1401 主要用于银行和保险公司从事磁带归档和打印服务
开发和维护完全不同的产品是昂贵的,同事不同的用户针对计算机的用途不同
如何解决二代计算机问题1:
卡片被拿到机房后能够快速的将作业从卡片读入磁盘,于是任何时刻当一个作业结束时,操作系统就能将一个作业从磁带读出,装进空出来的内存区运行,
同时的外部设备连接操作:SPOOLING,该技术同时用于输出,当采用了这种技术后,就不需要在IBM1401机了,也不必将磁带搬来搬去了
如何解决二代计算机问题3:
三代计算机操作系统广泛运用了二代计算机的操作系统没有的关键计算:多道技术
多道技术:
多道技术中的多道是指多个程序,多道技术的实现是为了解决多个程序竞争或者说共享同一个资源(比如CPU)的有序调度问题,解决方式即多路复用,多路复用分为时间上的复用和空间上的复用。
空间上的复用:将内存分为几个部分,每个部分放入一个程序,这样,同一时间内存中就有了多道程序
时间上的复用:当一个程序在等待I/O时,另一个程序可以使用cpu,如果内存中可以同时存放足够的作业,则cpu的利用率可以解决100%
空间上的复用最大问题是:程序直接的内存必须分割,这种分割是在硬件层面实现,由操作系统控制实现。如果内存彼此不分割,则一个程序可以访问另外一个程序的内存
首先丧失的就是安全性,比如你的qq程序可以访问操作系统的内存,那么就意味着你的qq可以拿到操作系统的所有权限
其次丧失的是稳定性,某个程序崩溃时,有可能把别人的内存也给回收了,比方说把操作系统的内存给回收了,则操作系统崩溃
第三代计算机操作系统仍然是批处理
许多程序员怀念第一代独享的计算机,可以及时调试自己的程序。为了满足程序员们很快可以等到响应,出现了分时操作系统
如何解决第二代计算机的问题2
分时操作系统:
多个联机终端+多道技术
20多个客户端同时加载到内存,有17个在思考,3个在运行,cpu就采用多道的方式处理内存中的3个程序,由于客户端提交的一般的简短的指令而且很少有耗时长的,索引计算机能够为许多用户提供快速的交互服务,所有的用户都以为自己独享计算机资源
CTTS:麻省理工兼容分时系统,知道第三代计算机广泛采用了必须保护硬件(程序之间的内存彼此隔离)之后,分时系统才开始流行
MIT:贝尔实验室和通用电气在CTTS成功研制后决定开发能够同时支持上百终端的MULTICS(其设计者着眼于建造满足波士顿地区所有用户计算需求的一台机器),很明显,这个项目GAMEOVER
后来一位参加过MULTICS研制的贝尔实验室计算机科学家Ken Thompson开发了一个简易的,单用户版本的MULTICS,这就是后来的UNIX系统。基于它浮生了很多其它的Unix版本,为了使程序能在任何版本的unix上运行,IEEE提出了一个UNIX标准,即posix(可移植的操作系统调用接口标准)
后来出现了minix,芬兰学生linus Torvalds基于它编写了Linux
第四代计算机(1980~至今):个人计算机
就是现在所用的计算机
操作系统的两大作用
作用一:为应用程序提供如何使用硬件资源的抽象
例如:操作系统提供了文件这个抽象概念,对文件的操作就是对磁盘的操作,有了文件我们无需再去考虑关于磁盘的读写控制
注意:
操作系统提供给应用程序的该抽象是简单,清晰,优雅的。为何要提出该抽象呢?
硬件厂商需要为操作系统提供自己的硬件驱动(设备驱动,这也是为何我们要使用声卡,就必须要安装声卡驱动..),厂商为了节省成本或者兼容旧的硬件,它们的驱动程序是复杂且丑陋的
操作系统就是为了隐藏这些丑陋的信息,从而为用户提供更好的接口
这样用户使用shell Gnome KDE看到的是不同的界面,但其实使用了同一套由Linux系统提供的抽象借口
作用二:管理硬件资源
现代的操作系统运行同时 运行多道程序,操作系统的任务就是在相互竞争的程序之间有序地控制对处理器,存储器以及其他I/O接口设备的分配
例如:同一台计算机上运行三个项目,它们三个想在同一时刻在同一台计算机上输出结果,那么开始的几行可能是程序1的输出,接着几行是程序2的输出,然后又是程序3的输出,最终将是一团糟(程序之间是一种相互竞争资源的过程)
操作系统将打印机的结果送到磁盘缓冲区,在一个程序完全结束后,才将暂存在磁盘上的文件送到打印机输出,同时其它的程序可以继续产生更多的输出结果(这些程序的输出结果并没有真正的送到打印机)。这样,操作系统就将由竞争产生的无序变成有序化
多路复用
现代计算机或者网络都是多用户的,多个用户不仅共享硬件,而且共享文件,数据库信息,共享意味着冲突和无序。
操作系统主要使用了:
1.记录那个程序使用什么资源
2.对资源进行请求分配
3.为不同的程序和用户调解互相冲突的资源请求
我们可以将上述操作系统的功能总结为:处理来自多个程序发起的多个(多个即多路)共享(共享即复用)资源的请求,简称为多路复用
多路复用有两种实现方式:
1.时间上的复用
当一个资源在时间上复用时,不同的程序或用来轮流使用它,第一个程序获取该资源使用结束后,在轮到第二个程序..第三个程序..
例如:只有一个cpu,多个程序需要在该cpu上运行,操作系统先把cpu分给第一个程序,在这个程序运行的足够长的时间(时间长短由操作系统的算法说的算)或者遇到I/O阻塞。那么操作系统则会把cpu分配给下一个程序,以此类推,知道第一个程序重新被分配到了cpu然后再次运行,由于cpu切换的速度很快,给用户的感觉就是这些程序是同时运行的,或者说是并发的,或者说是伪并行。至于资源如何实现时间复用,或者说谁应该是下一个要运行的程序,以及一个任务要运行多长时间,这些都是操作系统的工作。
2.空间上的复用
每个客户都获取一个大的资源中的一小部分资源,从而减少了排队等资源的时间。
例如:多个运行程序同时进入内存,硬件层面提供保护机制来确保各自的内存是分隔开的。且由操作系统控制,这比一个程序独占内存一个一个排队进入内存效率要高的多。
有关空间复用的其它资源还有磁盘,在许多系统中,一个磁盘同时为许多用户保存文件。分配磁盘空间并且记录谁正在使用哪个磁盘块 是操作系统资源管理的典型任务。
这两种方式合起来便是多道技术
处理器
什么是处理器
中央处理器(Central Processing Unit)的缩写,即CPU 计算机的大脑就是cpu,cpu是一个硬件,不同的cpu内部嵌入了不同的指令集,不同的指令集执行不同的程序
如SPARK指令集不能运行Pentium指令集程序,反之亦然
cpu的工作机制
cpu从内存中取出指令—>解码以确定该指令的类型和操作数—>执行
存在于cpu内部的存储部件:寄存器
cpu访问内存太慢了,于是有了用cpu材料制作的存储:存储器。与cpu材质相同意味着访问无延迟
寄存器工作机制
cpu指令中需要提供一些专门的指令用来将一个字从内存调入寄存器,以及将一个字从寄存器存入内存。其他的指令用来把来自寄存器和内存的操作数组合,或者两者产生一个结果,诸如将两个字相加并把结果存在寄存器或内存中
寄存器分为:
通用寄存器:保存关键变量和临时结果
程序计数器:对程序员可见的寄存器,保存了将要取出的下一条指令的内存地址。在指令取出后,程序计数器就被更新以便执行后续指令
堆栈指针:它指向内存中当前栈的顶端。该栈含有已经进入但还是没有推出的每个过程的一个框架。在一个过程的堆栈框架中保存了相关的输入参数,局部变量以及那些没有保存在寄存器中的临时变量
程序状态字psw:保存了条码位,cpu优先级,模式(用户态或者内核态),以及各种其他的控制,用户程序通过读入整个psw,但是只对其中的少量字段写入。在系统调用和i/o中,psw的作用很重要
操作系统和寄存器
操作系统必须知晓所有的寄存器。在时间多路复用的cpu中,操作系统经常会中止正在运行的某个程序并启动(或再启动)另一个程序。每次停止一个运行着的程序时,操作系统必须保存所有寄存器。这样在稍后该程序被再次运行时,可以把这些寄存器重新装入。
内核态与用户态
多数操作系统都有两种运行模式:内核态(也成为管态、核心态)和用户态。具体的,操作系统的执行即cpu的执行,每个cpu都有特定的指令集,我们所有的软件要运行,最终都需要转换成cpu的指令去运行,而cpu在运行时分为两种工作状态:内核态和用户态
注意:在嵌入式系统(该系统我们可以成为内核态)或解释系统(基于java的操作系统,它采用解释方式,而非硬件方式区分软件),上述的区分是模糊的
内核态与用户态的切换
操作系统通过控制cpu的psw寄存器中的一个2进制位来区分内核态和用户态
二进制位为1代表cpu此刻的运行状态为内核态,运行于内核态的程序如操作系统内核,可以执行任何的cpu指令,这意味着对硬件资源有完全的操作权限。
二进制位为0代表cpu此刻的运行状态为用户态,运行于用户态的程序如应用程序暴风影音,可以执行的是所有cpu指令集的一个子集(一部分指令),这个子集并不包含那些会影响机器的控制或可进行I/O的操作命令,这意味着在用户态的程序对硬件资源的操作是禁止的。
需要强调的是:针对用户态的用户应用程序对硬件操作,操作系统提供了系统调用的接口,这些接口程序同样是运行在用户态的,他们被用户应用程序调用,它们的功能是对操作系统内核发起请求,让运行陷入内核态,修改了二进制位1,进而可以执行操作硬件资源的指令
CPU设计演变
1.最开始这三个过程是同时进行的,这意味着任何一个过程完成都要等待其余两个过程执行完毕,浪费时间
2.后来被设计成流水线式,即解码同时可以取指
3.超变量cpu
4.多线程和多核芯片
moore定律指出,芯片中的晶体管数量每18个月翻一倍,随着晶体管数的增多,更强大的功能成为了可能,
1.在cpu芯片中加入了更大的缓存,一级缓存L1,用和cpu相等的材质制成,cpu访问它没有时延
2.一个cpu中的处理逻辑增多,intel公司首次提出,称为多线程(Multithreading)或超线程(Hyperthreading),对用户来说,一个有两个线程的cpu就相当于两个cpu,我们后面要学习的进程和线程知识就起源于这里,进程是资源单位而线程才是cpu的执行单位
多线程运行cpu保持两个不同的线程状态,可以在纳秒级的时间内来回切换,速度快到让你看到的结果是并发的,伪并行的,然后很多线程不提供真正的并行处理,一个cpu同时只能处理一个进程(一个进程中至少一个线程)
3.一个cpu包含2个或4个cpu芯片,要使用多核芯片必须要有多处理操作系统
存储器
计算机中第二重要的就是存储了,大部分人认为存储:速度快+容量大+价格便宜。然而同事兼备三者是不可能,所以就有了如下不同的处理方式
寄存器即L1缓存:与cpu相同材质制杖,访问无延时,容量<1KB
高速缓存即L2缓存:主要由硬件控制高速缓存的存取,内存中有高速缓存 行 按照0~64字节为行0,64~127为行1。
内存中的缓存行内容放在寄存器或者高速缓存中,当一个程序需要一个缓存字时,高速缓存硬件检测是否命中。
高速缓存命中通常树妖两个时钟周期
内存: 略
磁盘:略
磁带:再价钱相同的情况下对比硬盘拥有更高的存储容量,虽然速度低于磁盘,但是因为其容量大,在自然灾害下时可移动性强等特性,常用来作为备份
总线
北桥即PCI桥:连接高速设备
南桥即ISA桥:连接慢速设备