本文共 6050 字,大约阅读时间需要 20 分钟。
操作系统是一个软件系统,使计算机变得好用(将人从繁琐、复杂的对机器掌握的任务中解脱),是计算机运行变的有序。
根据管理资源不同,操作系统具体功能包括:
CPU管理,即如何分配cpu给不同的应用和用户。主要是进程管理,主要有三个目的,第一,公平,每个程序都有机会使用到CPU;
第二,非阻塞,任何程序不能无休止地阻挠其他程序的正常运行; 第三,优先级,优先级高的程序优先运行。内存管理,即如何分配内存给不同的应用和用户。内存专利主要是管理缓存、主存、磁盘、磁带等存储介质所形成的内存架构,内存管理的另一个目的是让很多程序共享同一个物理内存,这就需要对物理内存进行分割和保护,不让一个程序访问另一个程序所占内存空间,称为运行时不能越界。
外存管理,即如何分配磁盘给不同的用户和应用。主要是文件系统。
I/O管理,即如何分配输入输出设备给应用和用户。目的有两个:一是屏蔽不同设备的差异性,即用户用同样的方式访问不同的设备,从而降低变成的难度;二是提供并发访问,即将那些看上去并不具有共享性的设备,变得可以共享,如打印机。
第一阶段:状态机操作系统。
第二阶段:单一操作员、单一控制端操作系统。 第三阶段:批处理操作系统。一部分是控制程序执行,一部分是支持程序执行。 第四阶段:多道批处理操作系统。 第五阶段:1.分时操作系统。2.实时操作系统(计算机对这些应用必须在规定的时间内做出响应,不然就会发生事故或灾难),实时系统通常又分为软实时系统和硬实时系统。 第六阶段:现代操作系统中断:它是操作系统获得计算机控制权的根本保证。中断的基本原理是:设备在完成自己的任务后向CPU发出中断,CPU判断优先级,然后确定是否响应。如果响应,则执行中断服务程序,并在中断服务程序执行完后继续原来的程序。
内核态和用户态:实际上是处理器的一种状态,而不是程序的状态。内核态是特权态,而用户态是普通态。特权态下运行的程序可以访问任何资源,而用户态下的访问则受到限制。要限制一个程序对资源的访问,需要对程序执行的每一条指令进行检查才能完成,而这种检查就是地址翻译。程序发出的每一条指令都要经过这个地址翻译过来。通过对翻译的控制,就可以限制程序对资源的访问。系统处于内核态时,内核可以绕过内存地址翻译而直接执行特权指令。
进程:它指的是一个运行中的程序。在任何一个时候,进程所占有的全部资源,包括分配给该进程的内存、内核数据结构和软资源形成一个进程核(core)。核快照(Core Image)代表的是进程在某一特定时刻的状态。在linux或unix下编程,当出现分段错误(segmenttation fault)时,操作系统会自动进行核倒出(core dump)。“核倒出”把所有计算机的状态保存在一个文件中,通过阅读这个文件的内容可以的支出界时的进程状况,从而帮助进程调试。
内存:它是进程的存放场所,如何对内存进行管理,使得数据的读写具有高效率,高安全、高空间利用率和位置透明的特性是内存管理所要达到的目的。 文件:是操作系统提供的外部存储设备的抽象,它是程序和数据的最终存放地点。如何让用户的数据存放变得容易、方便、可靠和安全是文件系统要解决的问题。操作系统的服务是通过系统调用实现的。系统调用就是操作系统提供的应用程序界面(API)。用户程序通过调用这些API获得操作系统的服务。
系统调用按功能可以分为六大类:系统调用分为三个阶段:参数准备阶段、系统调用识别阶段、系统调用执行阶段。
进程就是进展中的程序,或者说晋城市执行中的程序。一个程序加载到内存后就变为进程。即:
进程=程序+执行
进程分为三种状态:执行、阻塞、就绪。
进程创建步骤:
进程空间也称为地址空间,地址空间就是进程要用的所有资源,所有资源构成了状态的划分。地址空间是“被动”的,只提供支持。进程与地址空间研究的主要内容是如何让多个进程空间共享一个物理内存。具体来说,就是高效、安全地让说有进程共享这片物理内存。
当一个进程产生时,操作系统就为其建立记录,操作系统用于维护进程记录的结构就是进程表或进程控制块(PCB,Process Control Block)。
维护的资料信息包括:寄存器、程序计数器、状态字、栈指针、优先级、进程ID、信号、创立时间、所耗CPU时间、当前持有的各种句柄等。
进程管理的最大问题就是资源分配。本质是追求公平,除了公平之外,还有一个问题要考虑:效率问题,也即最优。公平与效率就是进程管理中永恒的主题。
进程是运转的程序,是为了在CPU上实现多道编程而出现的概念,线程的出现是为了充分利用处理器的多核性能。
线程是CPU调度的基本单位。将进程分解为线程可以有效利用多处理器和多核计算机。线程是进程的分身,是进程的不同执行序列。
一般情况下线程共享和独享资源划分
线程共享资源 | 线程独享资源 |
---|---|
地址空间 | 程序计数器 |
全局变量 | 寄存器 |
打开的文件 | 栈 |
子进程 | 状态字 |
闹铃 | |
信号及信号服务程序 | |
记账信息 |
线程的管理有两种选择:一是让进程自己来管理线程,二是让操作系统来管理线程。不同的选择就出现了内核态线程和用户态线程,这也是线程实现的两种方式。由进程自己管理就是用户态县城实现,由操作系统管理就是内核态线程实现。
与管理进程一样,操作系统要管理线程,就要保持维护线程的各种资料,即将线程控制块放在操作系统内核空间,这样操作系统就同时保有进程控制块和线程控制块。根据它们提供的信息,操作系统就可以对线程进行各种类似进程的管理,如县城调度、线程的资源分配、各种安全措施的实现等。
线程在刚出现时,由于无法说服操作系统人员修改操作系统,实现方式只能是在用户态。用户自己做线程的切换,自己管理线程的信息,操作系统无需知道线程的存在。用户自己写一个执行系统(runtime system)作调度器(runtime scheduler),即除了正常执行任务的线程外,还有一个专门负责线程调度的线程。一个线程执行完一段时间后主动把资源释放给别人使用,而内核态则无须如此。在用户态实现情况下,执行系统的调度器也是线程,没有能力强行夺走控制权。(见下图)
鉴于用户态和内核态都存在缺陷,现代操作系统是将二者结合使用。用户态的执行系统负责进程内部线程在非阻塞时的切换,内核态的操作系统负责阻塞线程的切换,即同时实现内核态和用户态线程管理。内核态的线程数量较少,用户态的线程数量多,每个内核态线程可以服务一个或多个用户态线程,换句话就是,用户态线程被多路复用到内核态线程上。
由于一个进程通常包含多个线程,这多个线程之间因为资源共享就存在一种合作的关系,这种合作关系既可以相互独立也可以实现交互。这就是通信。
线程之间的交互称为线程通信。线程通信是从进程通信演变而来的,进程通信有个专用缩写,叫IPC(Inter-Process Communication)。由于每个进程至少有一个线程,所以进程之间的通信就是进程里面线程的通信。管道是一个线性字节数组,类似于文件,使用文件读写的方式进行访问。但却不是文件,因为通过文件系统看不到管道的存在,管道可以设在内存里,而文件很少设在内存里。在linux/unix系统中管道使用”|”。
如果要在两个不相关的线程,比如两个不同进程的线程之间进行管道通信,就需要使用记名管道。记名管道不能与文件系统命名文件重复,记名管道名称由两部分组成:计算机名和管道名。
使用套接字进行通信需要双方均创建一个套接字,其中一方作为服务器方,另一方作为客户方。
套接字按照传输媒介分为本地套接字和网域套接字。网域套接字分为:共享内存就是两个进程共同拥有同一片内存,这片内存中的任何内容,二者均可以访问。
注意:使用全局变量在同一个进程的线程间实现通信不称为共享内存。消息队列是一列具有头和尾的消息排列,新来的消息放在队列尾部,而读取消息则从队列头部开始。
线程同步的目的就是不管线程之间的执行如何穿插,其运行结果都是正确的。
两个或多个线程争相执行同一段代码或访问同一资源的现象称为竞争。这个造成竞争的共享代码段或资源就称为临界区。要避免竞争,就需要防止两个或多个线程同时进入临界区,这时候就需要协调手段。协调的目的就是在任何时刻只能有一个人在临界区,称为互斥。 互斥满足的四个条件:计算机程序分为计算密集型,I/O密集型,平衡型程序,进程调度就是为了实现对资源的合理管理、分配,实现利用率和效率的最大化。
CPU调度就是要达到极小化平均响应时间、极大化系统吞吐率、保持系统各个功能部件均处于繁忙态和某种公平的机制。
先来先到的一个隐含条件就是不能抢占,一个程序一旦启动就一直运行到结束或者受阻塞为止。
时间片轮换算法是对FIFO算法的一种改进,主要目的是改善短程序的响应时间,实现方式是周期性地进行程序切换。
短任务优先算法STCF(storted time to completion first),是为了改善短任务排在长任务后面轮转而造成响应时间和交互体验下降的办法而演变来的解决方案。具体来说,就是短任务的优先级比长任务的高,系统总是安排优先级高的程序优先执行。短任务优先有两个变种:非抢占和抢占。
系统率先执行优先级高的进程。
混合调度算法是为了解决以上调度算法缺陷而设计的。
实时调度算法种类较多,只介绍两种经典算法:动态优先级调度和静态优先级调度。动态优先级调度又称为最早截至任务优先算法EDF(earliest deadline first),而静态优先级调度又称为最短周期优先算法RMS(rate monotonic scheduling)。
在操作系统里,这种可以保证互斥的同步机制我们称为锁。
锁的基本操作
锁有两个基本操作:闭锁和开锁,闭锁就是将锁锁上,其他人进不来。开锁就是锁打开,可以进入。
死锁:如果一个进程集合中的每个进程都在等待只能由该进程集合中的其它进程才能引发的事件,那么,该进程集合就是死锁。
死锁发生的4个条件:
死锁发生的必要条件就是资源有限。即一个系统里面的资源数量有限,以至于无法同时满足所有线程的资源需求。
死锁的另外一个必要条件是持有等待。即一个县城在请求新的资源时,已经获得的资源并不释放,而是继续持有。
死锁的另一条件事不能抢占。如果一个资源可以抢占,则死锁也不会发生。
出现循环等待。
资源死锁(resource deadlock):在大多数情况下,每个进程多等待的事件就是释放该进程已经占有的资源。但是由于所有进程都不能运行,他们中的任何一个资源都无法释放资源,所以没有一个进程可以被唤醒。进程的数量以及占有或者请求的资源数量和种类都是无关紧要的,而且无论资源是何种类型都会发生这种结果。
资源死锁的条件:
互斥条件。每个资源要么已经分配给了一个进程,要么就是可用的。
占有和等待条件。已经得到某个资源的进程可以再请求新的资源。
不可抢占条件。已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显示的释放。
环路等待条件。死锁发生时,系统中一定有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。
死锁发生时,以上四个条件一定是同时满足的。如果以上任何一个条件不满足,死锁就不会发生。
消除资源独占条件
消除保持和请求条件
消除非抢占条件
消除循环等待条件
从死锁中恢复
利用抢占恢复
利用回滚恢复
通过杀死进程恢复
理想状态下的内存:大容量、高速度和持久性。现实内存架构为:缓存、主存、磁盘。
内存管理就是对内存架构进行管理,使程序在内存架构的任何一个层次上的存放对于用户来说都是一样的。用户无需担心自己的程序是存在缓存、主存、磁盘上。
1.地址保护:由于多道程序同时存在在内存中,操作系统要保证它们之间互不干扰,即一个进程不能随便访问另一个进程的地址空间。
2.地址独立:程序发出的地址与具有机器的物理主存地址是独立的。虚拟内存的核心思想就是把物理主存扩大到便宜、大容量的磁盘上,即将磁盘空间看作是主存空间的一部分。
虚拟内存要提供一个空间像磁盘那样大、速度像主存那样高的主存系统。在程序运行前就计算出所有物理地址,这种运行前即将物理地址计算好的方式叫做静态地址翻译。
多道编程内存管理:固定分区和非固定分区
固定分区:就是将内存分为固定的几个区域,每个区域的大小固定。
非固定分区:当一个程序想要运行时,内存不足,就必须排队等候另一个程序释放内存,然后分配此程序运行的相应内存。翻译地址的方法:物理地址=虚拟地址+程序所在区域的起始地址
访问地址满足以下条件就是合法访问: 程序所在区域的起始地址<=有效地址<=程序所在区域的起始地址+程序长度 由此可见,只要设置两个端值:基址和极限,即可达到地址翻译和地址保护的目的。