操作系统总结

计算机组成

操作系统总结 

主要硬件包括CPU(算术、逻辑单元)、主存、辅助存储、系统总线、I/O设备(即输入输出)。

CPU:

CPU本身(Processor)可以是单核、多核、多CPU架构,主要目的就是满足日益增长的运算需求。单核比较简单,多核(包括一CPU多核心和多CPU)立即涉及到核心之间高速缓存的共享,此处是CPU内置高速缓存非主存,进程之间寄存器数据的共享和进程处理器调度问题。

总线:

总线连接了所有的设备提供通讯的能力,注意设备之间同一时间的通信是会冲突的,这就要涉及到总线的决策,负责决策的可能是CPU或专有芯片。所有设备需要通信时要提交通信请求有CPU决定下一个通信的设备。

另外一个问题显然连接到总线上的设备越多,冲突的几率就越大效率越差。所以总线可以有多层总线设计,比如设置I/O总线所有的I/O设备都通过I/O总线和I/O控制器连接,I/O控制器则连接在系统总线上代理I/O的通信请求。

速度:

CPU飞快,其中CPU内置的一级高速缓存保持了和CPU同样的速度但是容量极小,接下来可能存在二级、三级高速缓存;主存(内存)其次和CPU存在数量级上的差距;辅寸(多硬盘)的速度就不是一般的慢了,因为有机械运动,但是容量大很多;I/O设备多数慢的要死,但不是没有快的(比如图形、千兆以太网的速度是超过硬盘的)。总而言之就是快的太贵,贱的太慢,访问快的断电数据即失效,不失效的访问慢,所以就有了多级存储的设计。程序的运行必然是加载到主存的(内存)!

局部性:

多级存储的设计得益于局限性能够大幅提升性能。局限性本身分为时间局限性和空间局限性。时间局限性是说现在用到的指令很可能短时间内还会多次调用,空间局限性是现在调用的数据在辅寸上邻接的块很可能即将被用到。就是因为局限性的存在预读取才有了市场(所以有了磁盘整理),当然局限性是必然的——程序肯定趋向于统一存取、循环、分支逻辑肯定是指令的循环调用。——好的命中率决定了计算机的性能。

指令周期(取指周期):

计算机中CPU始终是取指-》执行的动作循环运行的,计算机从取指到完成指令的周期称为取指周期。因此针对CPU的性能优化有流水线和超标量体系结构,前者目的在于合理分割指令使取指和执行能够并行进行(预取指),后者则通过相同的运算结构重复设置实现多条指令同时执行(得益于指令的乱序执行)。

I/O设备进化:

I/O设备一般较慢,极端点的比如键盘这货简直慢的没法说。那么当程序需要读取I/O数据时(如读取一块数据、监听键盘输入)就会被I/O设备阻塞,这是最差的情况整个系统空转直到I/O设备读取数据完成。

于是有了可编程I/O设备——你可以定期问我准备好数据了没,好了你就取没好你就干别的去,也就是轮询这法子还是非常慢因为CPU要定期过来问而且多数情况都是没准备好空耗系统资源(进程切换)。

再后来有了中断,前提是指令的运行是可被中断和恢复的(现在当然都可以,把寄存器数据保存到缓存,完了再恢复嘛),需要读取的时候CPU发给I/O指令然后不理它了,需要读取的进程(或线程)进入阻塞状态换下一个进程来执行,当I/O准备好数据后发送一个中断信号给CPU,这时现在执行的进程被中断CPU会执行一段中断处理程序(通常很短)把之前阻塞的进程标记为Ready(可执行)状态,处理完中断后恢复之前中断的进程(或线程)继续执行。在当前进程执行完或者超时中断后(分时多道程序处理,超时也是一种中断),之前从阻塞中恢复的进程可能会被执行(取决于进程调度,不一定是下一个时间片里也可能是下几个时间片后或者干脆饿死了)。

再后来又有了DMA(直接存储器访问),主要原因就是CPU很忙,你一个拷贝/传输整块数据的动作就不要每块数据都让我来处理了,系统中多了一个专门的辅助芯片干这个事情。CPU下达指令后辅助芯片负责设备之间的数据直接传输。DMA模块可以是总线中的一个模块也可以是I/O模块,但是仍然要占用总线(传输数据)所以并不是不会对系统性能产生影响,至少DMA冲突时CPU要等待一个总线周期。

操作系统

操作系统总结 

多线程定义

多线程是指进程内支持并发路径执行的能力。

与进程的关系

一个进程至少包含一个线程,当进程中存在多个线程的时各个线程可以共享进程内的资源。进程内的线程共享进程的用户空间,操作系统仍然通过进程控制块控制进程进而影响到线程。线程本事具备自己的线程控制块、用户栈和系统栈。

创建方式

由于线程类型的不同(下面介绍)线程可以是操作系统创建的也可以使通过线程库(Lib)由进程自己创建的,对于进程创建的线程操作系统是不知道的。

线程优势

l 创建时间开销远小于进程的创建。因为不需要分配用户空间和那么多初始化动作。

l 销毁线程的成本也远低于进程。

l 线程之间的切换消耗低于进程,特别是同一进程内的线程切换消耗更低。

l 线程间通信的效率比进程间通信要高,因为进城之间安全性问题需要隔离和互斥,同一进程内的线程可以共享进程资源而不需要提前获取锁。

线程同步

进程也涉及到同步,但是线程的同步更需要开发者注意。上面提到了线程共享进程的资源并且不需要获取锁,所以线程之间是没有操作系统来保证隔离的。

线程类型

类型分为用户级线程和内核级线程。用户级线程即通过Lib创建的对操作系统是透明的,内核级线程是由操作系统创建的。

用户级

内核级

通过线程库创建,对操作系统不可见

由操作系统来管理

比内核级的线程更高效,不涉及模式切换

在线程切换时需要模式切换(因为是调用系统级的指令)

进程中同时只能有一个线程在运行,还是多段程序的思路

线程可以并发运行,特别指多核计算机

一旦被阻塞整个进程就被阻塞,也就是所有的线程都完蛋了

只会阻塞引起阻塞的线程

 

线程的四个应用场景

l 前后台运算:即有UI和后台运算的程序,你总不希望后台数据运算时前面的UI界面就对用户没响应了吧以这里应该分开线程,后台启动单独的线程运算,界面在不同的线程了所有能时时相应用户的操作(哪怕只是提示计算中)。

l 异步计算:比如应对电路故障的实时备份功能,通过线程无论是在代码量上还是开销上都要比你编写定时调度的功能要高效。

l 速度敏感的运算:多线程的计算机可以在计算一组数据的同时读入下一组数据(当然弄几个进程干这事儿也可以,但是开销明显更大)。

l 模块化的程序架构:对于包含多个活动或者多个源头和目标的输入输出程序,也许更容易使用多线程来设计和实现(就是每个线程干一摊子事儿,大家数据在一起自己取谁也别干涉谁)。

l 另外的比如Java程序,每个程序就是一个JVM的进程,至于这里面你起多少线程操作系统是不关心的。

 

并发性

操作系统总结

资源类型

可重用资源:比如I/O设备、文件等等,它们在同一时间只可以被一个进程使用,但是使用之后并不会因此而销毁。

可消耗资源:比如存在I/O中的一段流数据,一旦被使用就不在存在了,但是可以被制造出来。除此以外还有信号、中断、消息等等。

死锁形成的条件

1.互斥

2.不存在抢占

3.持有和等待

4.形成了等待的环路

1~3:有可能产生死锁但是并没死锁。只有4发生的时候死锁才是真的产生了。

死锁预防(protection)

死锁的预防不同于死锁避免,死锁预防的目的在于干涉死锁形成的条件1~4使得死锁无法形成,往往导致的成本很高并且不很实用。

1.互斥:无法消除,有并发就有互斥。

2.抢占:这个可以做到有几种途径:a,当进程资源请求被拒绝时强制其释放已占有的资源,在后续需要时可以重新申请。b,当进程申请已被其它进程占有的资源时系统允许其抢占。这两种方法都有一个大前提就是资源状态必须是容易保存和恢复的,否则就啥都没了。

3.持有和等待:可以让进程一次申请所有需要的资源,这将不会出现持有并等待的情况。但是这是在进程能够预测它所使用的所有资源的前提下才成立的,并且效率很低。进程会在没有用到资源前先占用资源。

4.形成环路:可以将各个资源类型定义成线性顺序,只有占有了前面资源的进程才能进一步申请后续资源——同样效率是硬伤。

 

死锁避免(avoidance)

死锁的避免是运行时发现进程的启动或者请求会导致死锁,从而采取不启动或阻塞的措施。

1,如果进程的请求导致死锁,则不启动进程。这个比较难做到,因为它要求进程提前预知自己要用到的所有资源。

2,如果进程请求的资源可能导致死锁,则不分配资源给进程(塞你一会儿)。这个是更可行的办法。

方法2的运算如下:

OS中始终维护下列数据:

1,矩阵C(claim)为各个进程声明的需要用到资源。

2,矩阵A(allocation)现在以分配给各个进程的情况。

3,向量R当前系统拥有的资源

当一个进程申请起源是,OS假设分配资源给它并更下上面的数据,之后查看是否会产生死锁:

1,C – A得到矩阵P描述每个进程顺利完成时要得到的剩余资源。

2,向量R – A中各个资源的合计值等到向量V当前可用的资源。

3,如果向量V中的资源不足以使P中任何一个进程得到满足,那么即将发生死锁,这时候拒绝进程的请求。

4,如果存在可完成的进程,把进程的资源加入到向量V中重复3步骤直到所有进程可完成或出现死锁。

 

R1

R2

R3

P1

3

2

2

P2

6

1

3

P3

3

1

4

P4

4

2

2

矩阵C

 

 

R1

R2

R3

P1

1

0

0

P2

6

1

2

P3

2

1

1

P4

0

0

2

矩阵A

 

R1

R2

R3

P1

2

2

2

P2

0

0

1

P3

1

0

3

P4

4

2

0

矩阵C – A

R1

R2

R3

9

3

6

系统资源向量R

R1

R2

R3

0

1

1

当前可用资源向量V

由于当前可用资源可以满足P2,所以可以加回P2的资源并重复步骤3。

死锁的检测和恢复

死锁的检测其实和上面的步骤是一样的需要两个矩阵:Q——进程请求资源(是排除已分配资源后)、A——进程已经分配的资源,一个向量V当前可用资源。

1,标记A中所有资源占用都为0的进程行。

2,初始化临时的向量W是它等于V。

3,查找Q中为标记的i行,其中i行小于向量W。如果找不到i则种植算法。

4,如果找到i行,将i标记并把A中i行数据加回到W中。重复步骤3。

当算法结束时如果存在为标记的行则已经发生死锁。

 

死锁的恢复有点野蛮:

1,取消所有死锁的进程。这是现代操作系统最常用的办法。

2,回滚进程到之前一个检查点(checkpoint),重新启动。操作系统需要具备回滚和恢复的能力,这样仍然有死锁的风险,但是并发的不确定性能保证死锁最终不再发生。

3,连续取消死锁进程直到最终不再出现死锁。取消进程的顺序依赖某种成本的原则,取消后重新调用死锁检测,如果仍然存在死锁继续取消。

4,连续抢占资源直到死锁不再发生。同样基于某些成本选择的方法,资源抢占后重新调用死锁检测,一个被抢占资源的进程需要回滚到获取该资源前的检查点。

3、4步骤可以考虑一下原则:

l 目前消耗处理器时间最少。

l 目前为止产生的输出最少

l 预计剩下的时间最长。

l 目前位置分配的资源总量最少。

l 优先级最低。

哲学家就餐问题

一个屋子里有5个哲学家他们一天中除了睡觉只做思考和吃饭两件事情,屋子里有一个桌

来源:chuozou0913

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2013年11月24日
下一篇 2013年11月24日

相关推荐