操作系统 精髓与设计原理第五版.docx
- 文档编号:24630888
- 上传时间:2023-05-29
- 格式:DOCX
- 页数:31
- 大小:110.16KB
操作系统 精髓与设计原理第五版.docx
《操作系统 精髓与设计原理第五版.docx》由会员分享,可在线阅读,更多相关《操作系统 精髓与设计原理第五版.docx(31页珍藏版)》请在冰豆网上搜索。
操作系统精髓与设计原理第五版
第一章:
计算机系统概述
计算机系统基本组成
I.处理器:
控制计算机的操作,执行数据处理功能。
当只有一个处理器时,它通常指中央处理器(CPU)。
II.主存储器:
存储数据和程序。
iii.输入/输出模块:
在计算机和外部环境之间移动数据。
iv.系统总线:
为处理器、主存储器和输入输出模块提供通信的设施。
什么是中断?
中断是指计算机的处理机用来处理外来请求或内部错误的一种机制,该机制软硬件结合,使得计算机的处理机能够暂停当前指令系列的执行而转向请求指令系列的执行。
1.将计算机的处理机正在执行的指令系列称为当前指令系列,当前指令系列通常是用户程序。
2.将计算机为处理各类突发(非预期)事件请求(I/O请求,时钟请求,程序错误,硬件错误)而有待执行的指令系列称为请求指令系列,通常称为中断处理程序,是操作系统的一部分。
3.请求指令系列执行期间,可以被其它事件中断(在允许多重中断的情况下)。
4.执行请求指令系列完毕后,可以返回被暂停的原始指令系列,也可以不返回(在多道程序设计环境中)。
5.中断处理程序与社会事务中的应急事件的预案类似。
进程与程序的区别:
进程
程序
1.进程是执行中的程序,还涉及数据和上下文环境,因而有动态性。
1.程序具有稳健性。
2.一个进程可包含多个程序段。
2.一个程序可对应多个进程(不同时间,不同机器,不同数据,不同上下文)。
3.进程中的程序是指可执行程序。
3.广泛意义下的程序可以是任何意义上的程序。
4.进程中的数据是“值”。
4.程序中的数据是指数据结构,是“型”,“名”,联系。
5.进程中涉及上下文(基本性质是与进程本身以及资源有关的状态信息)。
5.程序不涉及上下文。
6.进程失去逻辑封闭性(原因是多个进程间是异步,并发或并行的),需要一定的互斥机制才能保证逻辑封闭性。
6.程序具有逻辑封闭性,输入决定输出。
中断处理
中断的发生激活了很多事情,包括处理器硬件中的事件及软件中的事件。
1.设备给处理器发出一个中断信号。
2.处理器在响应中断前结束指令系列的执行。
3.处理器对中断进行测定,确定存在未响应的中断,并给提交中断的设备发送确认信号,确认信号允许该设备取消它的中断信号。
4.处理器需要把处理权转移到中断程序中去做准备。
首先,需要保存从中断点恢复当前程序所需要的信息,要求的最少信息包括程序状态字(PSW)和保存在程序计数器中的下一条执行的指令地址,它们被压入系统控制栈中(参见附录1B)。
5.处理器把响应此中断的中断处理器入口地址装入程序的计数器中。
6.在这一点,与被中断程序相关的程序计数器和PSW被保存到系统栈中。
此外,还有一些其他信息被当作正在执行程序的状态的一部分。
7.中断处理器现在可以开始处理中断,其中包括检查与I/O操作相关的信息或其他引起中断的事件,还可能包括给I/O设备发送附加命令或应答。
8.当中断处理结束后,被保存的寄存器值从栈中释放并恢复到寄存器中。
9.最后的操作是从栈中恢复PSW和程序计数器的值,其结果是下一条要执行的指令来自被中断的程序。
处理多重中断的方法:
处理多重中断有两中方法:
1.当正在处理一个中断时,禁止再发生中断。
禁止中断的意思是处理器将对任何新的中断请求信号不予理睬。
2.定义中断优先级,允许高优先级的中断打断优先级低的中断处理器的运行。
第二章:
操作系统概述
操作系统通常提供的服务:
1.程序开发
2.程序运行
3.I/O设备访问
4.文件访问控制
5.系统访问
6.错误检测和响应
7.审计
作为资源管理器的操作系统
1.操作系统与普通的计算机软件作用相同,也就是说,它由处理器执行的一段程序或一组程序。
2.操作系统经常会释放可控制,而且必须以来处理器才能恢复。
操作系统开发中的五个主要理论成就
1.进程
2.内存管理
3.信息保护和安全
4.调度和资源管理
5.系统结构
进程
进程的概念是操作系统结构的基础。
1.一个正在执行的程序
2.计算机中正在运行的程序的一个实例
3.可分配给处理器并由处理器执行的一个实体
4.由单一的顺序的执行线索、一个当前状态和一组相关的系统资源所描述的活动单元
计算机系统发展的三条主线:
多道程序批处理操作、分时和实时事务系统,它们在时间和同步中所产生的问题推动了进程概念的发展。
1.多道程序设计是为了让处理器和I/O设备(包括存储设备)同时保持忙状态,以实现最大效率。
其关键机制是,在响应表示I/O事务结束的信号时,操作系统将对主存中驻留的不同程序进行处理器切换。
2.通用的分时。
其主要设计目标是能及时响应单个用户的要求,但是由于成本原因,又要可以同时支持多个用户。
由于用户反应时间相对较慢,因此这两个目标是可以同时实现的。
3.实时事务处理系统。
在这种情况下,很多用户都在对数据库进行查询或修改,此时系统响应时间是最终要的。
进程的组成:
1.一段可执行的程序
2.程序所需要的相关数据(变量、工作空间、缓冲区等)
3.程序的执行上下文
最后一部分是根本。
执行上下文又称为进程状态,是操作系统用来管理和控制进程所需的内部数据。
这种内部信息是分开的,因为操作系统信息不允许被进程直接访问。
上下文包括操作系统管理进程以及处理器正确执行进程所需要的所有信息,包括处理器的内容,如程序计数器和数据寄存器。
他还包括操作系统使用的信息,如进程优先级以及进程是否在等待特定I/O事件的完成。
操作系统担负的五个基本的存储器管理责任:
1.进程隔离:
操作系统必须保护独立的进程,防止互相干涉数据和存储空间。
2.自动分配和管理:
程序应该根据需要在存储层间动态地分配,分配对程序员来说是透明的。
3.支持模块化程序设计:
程序员应该能够定义程序模块,并且动态地创建、销毁模块,改变模块大小。
4.保护和访问控制
5.长期存储
操作系统的几种不同方法和设计要素:
1.微内核体系结构
2.多线程
3.对称多处理
4.分布式操作系统
5.面向对象设计
多线程
多线程技术是指把执行一个应用程序的进程划分程可以同时执行的多个线程。
线程和进程的区别:
线程:
可分派的工作单元。
它包括处理器上下文(包括程序计数器和栈指针,)和栈中自己的数据区域(为允许子程序分支)。
线程顺序执行,并且是可中断的,这样处理器就可以转到另一线程。
进程:
一个或多个线程和相关系统资源(如包含相互据和代码的存储器空间、打开的文件和设备)的集合。
这紧密对应于一个正在执行的程序的概念。
通过把一个应用程序分解成多个线程,程序员可以在很大程度上控制应用程序的模块性和应用程序相关事件的时间安排。
对称多处理(SymmetricMultiProcessing,SMP):
对称多处理可定义为具有以下特征的一个独立的计算机系统:
1.有多个处理器。
2.这些处理器共享同一个主存储器和I/O设备,它们之间通过通信总线或其他内部连接方案互相连接。
3.所有处理器都可以执行相同的功能(因此称为对称)。
对称多处理操作系统可以调度进程或线程得到所有的处理器运行。
对称多处理器结构比单处理器结构具有更多的潜在优势。
第三章进程描述和控制
在进程执行时,任意给定一个时间,进程都可以唯一地表征为以下元素:
1.标识符:
跟这个进程相关的唯一标识符,用来区别其他进程。
2.状态:
如果进程正在执行,那么进程处于执行态。
3.优先级:
相对于其他进程的优先级。
4.程序计数器:
程序中即将被执行的下一条指令的地址。
5.内存指针:
包括程序代码和进程相关数据的指针,还有其他进程共享内存块的指针。
6.上下文数据:
进程执行的处理器的寄存器中的数据。
7.I/O状态信息:
包括显示的I/O请求、分配给进程的I/O设备(例如磁带驱动器)和被进程使用的文件列表等。
8.审计信息:
可包括处理器时间总和、使用的时钟数总和、时间限制、审计号等。
导致进程创建的原因:
1.新的批处理作业:
通常位于磁带或磁盘中的批处理作业控制流被提供给操作系统。
当操作系统准备接纳新工作是,它将读取下一个作业控制命令。
2.交互登录:
终端用户登录到系统。
3.操作系统因为提供一项服务而创建:
操作系统可以创建也个进程,代表用户程序执行一个功能,使用户无需等待(如控制打印的任务)。
4.由现有的进程派生:
基于模块化的考虑,或者为了开发并行性,用户程序可以指示创建多个进程。
进程派生
当操作系统为另一个进程的显示请求创建一个进程时,这个动作称为进程派生。
当一个进程派生另一个进程时,前一个进程称为父进程,被派生的进程称为子进程。
在典型情况下,相关进程需要相互之间的通讯和合作。
导致进程终止的原因:
1.正常完成:
进程自行执行一个操作系统服务调用,表示它已经结束运行
2.超过时限:
进程运行时间超过规定的时限。
3.无可用内存:
系统无法满足系统需要的内存空间
4.越界:
进程试图访问不允许访问的内存单元。
5.保护错误:
进程试图使用不允许使用的资源或文件,或者试图以一种不正确的方式使用,如:
往制度文件中写。
6.算术错误:
进程试图进行被禁止的计算,如除以零或者存储大于硬件可以接纳的数字
7.时间超出:
进程等待某一事件发生的时间超过了规定的最大值。
8.I/O失败:
在输入或输出期间发生错误,如找不到文件、在超出规定的最多努力次数后仍然读写失败。
9.无效指令:
进程试图执行一个不存在的指令。
10.特权指令:
进程试图使用为操作系统保留的指令。
11.数据误用:
错误类型或未初始化的一块数据。
12.操作员或操作系统干涉:
由于某些原因,操作员或操作系统终止进程(例如,如果存在死锁)。
13.父进程终止:
当一个父进程终止时,操作系统可自动终止该进程的所有后代进程。
14.父进程请求:
父进程通常具有终止其任何后代进程的权利。
进程状态转换图
挂起状态进程:
挂起状态进程的概念与不再主存中的进程概念是等价的。
挂起状态进程的特点如下所示:
1.进程不能立即执行。
2.进程可能是或不是正在等待一个事件。
如果是,阻塞条件不依赖于挂起条件,阻塞事件的发生不会使进程立即被执行。
3.为阻止进程执行,可以通过代理把这个进程至于挂起状态,代理可以是进程自己,也可以是父进程或操作系统。
4.除非代理显示地命令系统进行状态转换,否则进程无法从这个状态中转移。
进程挂起的原因:
1.交换:
操作系统需要释放足够的主存空间,以调入并执行处于就绪态的进程。
2.其他OS原因:
操作系统可能挂起后台进程或工具程序进程,或者被怀疑导致问题的进程。
3.交互式用户请求:
用户可能希望挂起一个程序的执行,目的是为了调试或者与一个资源的使用进行连接。
4.定时:
一个进程可能会周期性地执行(例如审计或系统监视进程),而且可能在等待下一个时间间隔时被挂起。
5.父进程请求:
父进程可能会希望挂起后代进程的执行,以检查或修改挂起的进程,或者协调不同后代进程之间的行为。
进程控制块PCB(ProcessControlBlock):
存放进程的管理和控制信息的数据结构称为进程控制块。
它是进程管理和控制的最重要的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。
在不同的操作系统中对进程的控制和管理机制不同,PCB中的信息多少也不一样,通常PCB应包含如下一些信息。
1、进程标识符name:
每个进程都必须有一个唯一的标识符,可以是字符串,也可以是一个数字。
UNIX系统中就是一个整型数。
在进程创建时由系统赋予。
2、进程当前状态status:
说明进程当前所处的状态。
为了管理的方便,系统设计时会将相同的状态的进程组成一个队列,如就绪进程队列,等待进程则要根据等待的事件组成多个等待队列,如等待打印机队列、等待磁盘I/O完成队列等等。
3、进程相应的程序和数据地址,以便把PCB与其程序和数据联系起来。
4、进程资源清单。
列出所拥有的除CPU外的资源记录,如拥有的I/O设备,打开的文件列表等。
5、进程优先级priority:
进程的优先级反映进程的紧迫程序,通常由用户指定和系统设置。
UNIX系统采用用户设置和系统计算相结合的方式确定进程的优先级。
6、CPU现场保护区cpustatus:
当进程因某种原因不能继续占用CPU时(等待打印机),释放CPU,这时就要将CPU的各种状态信息保护起来,为将来再次得到处理机恢复CPU的各种状态,继续运行。
7、进程同步与通信机制用于实现进程间互斥、同步和通信所需的信号量等。
8、进程所在队列PCB的链接字根据进程所处的现行状态,进程相应的PCB参加到不同队列中。
PCB链接字指出该进程所在队列中下一个进程PCB的首地址。
9、与进程有关的其他信息。
如进程记账信息,进程占用CPU的时间等。
进程执行模式:
非特权模式通常称为用户模式,这是因为用户程序通常在该模式下运行;特权模式可称为系统模式、控制模式或内核模式,内核模式指的是操作系统的内核,这是操作系统中包含重要系统功能的部分。
操作系统内核的典型功能:
进程管理:
1.进程的创建和终止。
2.进程的调度和分配。
3.进程切换。
4.进程同步以及对进程间通信的支持。
5.进程控制块的管理。
内存管理:
1.给进程分配地址空间。
2.交换。
3.页和段的管理。
I/O管理:
1.缓冲区管理。
2.给进程分配I/O通道和设备。
支持功能:
1.中断处理
2.审计
3.监视
进程的创建:
1.给新进程分配一个唯一的进程标识号。
2.给进程分配空间。
3.初始化进程控制块。
4.设置正确的连接。
5.创建或扩充其他数据结构。
UNIX下进程创建的方法:
(摘自:
在UNIX系统中,用户创建一个新进程的唯一方法就是调用系统调用fork。
调用fork的进程称为父进程,而新创建的进程叫做子进程。
系统调用的语法格式:
pid=fork();
在从系统调用fork中返回时,两个进程除了返回值pid不同外,具有完全一样的用户级上下文。
在子进程中,pid的值为零。
在系统启动时由核心内部地创建的进程0是唯一不通过系统调用fork而创建的进程。
核心为系统调用fork完成下列操作:
为新进程在进程表中分配一个空项。
为子进程赋一个唯一的进程标识号(PID)。
做一个父进程上下文的逻辑副本。
由于进程的某些部分,如正文区,可能被几个进程所共享,所以核心有时只要增加某个区的引用数即可,而不是真的将该区拷贝到一个新的内存物理区。
增加与该进程相关联的文件表和索引节点表的引用数。
对父进程返回子进程的进程号,对子进程返回零。
理解系统调用fork的实现是十分重要的,因为子进程就象从天而降一样地开始它的执行序列。
下面是系统调用fork的算法。
核心首先确信有足够的资源来成功完成fork。
如果资源不满足要求,则系统调用fork失败。
如果资源满足要求,核心在进程表中找一个空项,并开始构造子进程的上下文。
算法:
fork
输入:
无
输出:
对父进程是子进程的PID
对子进程是0
{
检查可用的核心资源
取一个空闲的进程表项和唯一的PID号
检查用户没有过多的运行进程
将子进程的状态设置为“创建”状态
将父进程的进程表中的数据拷贝到子进程表中
当前目录的索引节点和改变的根目录(如果可以)的引用数加1
文件表中的打开文件的引用数加1
在内存中作父进程上下文的拷贝
在子进程的系统级上下文中压入虚设系统级上下文层
/*虚设上下文层中含有使子进程能
*识别自己的数据,并使子进程被调度时
*从这里开始运行
*/
if(正在执行的进程是父进程){
将子进程的状态设置为“就绪”状态
return(子进程的PID)//从系统到用户
}
else{
初始化计时区
return0;
}
}
我们来看看下面的例子。
该程序说明的是经过系统调用fork之后,对文件的共享存取。
用户调用该程序时应有两个参数,一个是已经有的文件名,另外一个是要创建的新文件名。
该进程打开已有的文件,创建一个新文件,然后,假定没有遇见过错误,它调用fork来创建一个子进程。
子进程可以通过使用相同的文件描述符而继承地存取父进程的文件(即父进程已经打开和创建的文件)。
当然,父进程和子进程要分别独立地调用rdwrt函数,并执行一个循环,即从源文件中读一个字节,然后写一个字节到目标文件中区。
当系统调用read遇见文件尾时,函数rdwrt立即返回。
#include
intfdrd,fdwt;
charc;
main(intargc,char*argv[])
{
if(argc!
=3){
exit
(1);
}
if((fdrd=open(argv[1],O_RDONLY))==-1){
exit
(1);
}
if((fdwt=creat(argv[2],0666))==-1){
exit
(1);
}
fork();
//两个进程执行同样的代码
rdwrt();
exit(0);
}
rdwrt()
{
for(;;){
if(read(fdrd,&c,1)!
=1){
return;
}
write(fdwt,&c,1);
}
}
在这个例子中,两个进程的文件描述符都指向相同的文件表项。
这两个进程永远不会读或写到相同的文件偏移量,因为核心在每次read和write调用之后,都要增加文件的偏移量。
尽管两个进程似乎是将源文件拷贝了两次,但因为他们分担了工作任务,因此,目标文件的内容依赖于核心调度两个进程的次序。
如果核心这样调度两个进程:
使他们交替地执行他们的系统调用,或甚至使他们交替地执行每对read和write调用,则目标文件的内容和源文件的内容完全一致。
但考虑这样的情况:
两个进程正要读源文件中的两个连续的字符"ab"。
假定父进程读了字符"a",这时,核心在父进程写之前,做了上下文切换来执行子进程。
如果子进程读到字符"b",并在父进程被调度前,将它写到目标文件,那么目标文件将不再含有字符串"ab",而是含有"ba"了。
核心并不保证进程执行的相对速率。
再来看看另外一个例子:
#include
charstring[]="Hello,world";
main()
{
intcount,i;
intto_par[2],to_chil[2];//到父、子进程的管道
charbuf[256];
pipe(to_par);
pipe(to_chil);
if(fork()==0){
//子进程在此执行
close(0);//关闭老的标准输入
dup(to_child[0]);//将管道的读复制到标准输入
close
(1);//关闭老的标准输出
dup(to_par[1]);//将管道的写复制到标准输出
close(to_par[1]);//关闭不必要的管道描述符
close(to_chil[0]);
close(to_par[0]);
close(to_chil[1]);
for(;;){
if((count=read(0,buf,sizeof(buf))==0)
exit();
write(1,buf,count);
}
}
//父进程在此执行
close
(1);//重新设置标准输入、输出
dup(to_chil[1]);
close(0);
dup(to_par[0]);
close(to_chil[1]);
close(to_par[0]);
close(to_chil[0]);
close(to_par[1]);
for(i=0;i<15;i++){
write(1,string,strlen(string));
read(0,buf,sizeof(buf));
}
}
子进程从父进程继承了文件描述符0和1(标准输入和标准输出)。
两次执行系统调用pipe分别在数组to_par和to_chil中分配了两个文件描述符。
然后该进程执行系统调用fork,并复制进程上下文:
象前一个例子一样,每个进程存取自己的私有数据。
父进程关闭他的标准输出文件(文件描述符1),并复制(dup)从管道线to_chil返回的写文件描述符。
因为在父进程文件描述符表中的第一个空槽是刚刚由关闭腾出来的,所以核心将管道线写文件描述符复制到了文件描述符表中的第一项中,这样,标准输出文件描述符变成了管道线to_chil的写文件描述符。
父进程以类似的操作将标准输入文件描述符替换为管道线to_par的读文件描述符。
与此类似,子进程关闭他的标准输入文件(文件描述符0),然后复制(dup)管道线to_chil的读文件描述符。
由于文件描述符表的第一个空项是原先的标准输入项,所以子进程的标准输入变成了管道线to_chil的读文件描述符。
子进程做一组类似的操作使他的标准输出变成管道线to_par的写文件描述符。
然后两个进程关闭从pipe返回的文件描述符。
上述操作的结果是:
当父进程向标准输出写东西的时候,他实际上是写向to_chil--向子进程发送数据,而子进程则从他的标准输入读管道线。
当子进程向他的标准输出写的时候,他实际上是写入to_par--向父进程发送数据,而父进程则从他的标准输入接收来自管道线的数据。
两个进程通过两条管道线交换消息。
无论两个进程执行的顺序如何,这个程序执行的结果是不变的。
他们可能去执行睡眠和唤醒来等待对方。
父进程在15次循环后退出。
然后子进程因管道线没有写进程而读到“文件尾”标志,并退出。
进程的切换:
进程切换的功能是很简单的。
在某一时刻,一个正在运行的进程被中断,操作系统制定另一个进程为运行态,并把控制权交给这个进程。
进程切换的步骤:
1.保存处理器上下文,包括程序计数器和其他寄存器。
2.更新当前处于运行太的进程的进程控制块,包括进程状态改变为另一状态(就绪态、阻塞太、就绪/挂起态或退出态)。
还必须更新其他相关域,包括离开运行态的原因和审计信息。
3.把进程的进程控制块移到相应的队列(就绪、在事件i处阻塞、就绪/挂起)。
4.选择另一个进程执行。
5.更新所选择进程的进程控制块,包括把进程的状态变为运行态。
6.更新内存管理的数据结构,这取决于如何管理地址转换。
7.恢复处理器在被选择的进程的最后一次切换出运行态时的上下文,这可以通过载入程序设计数据和其他寄存器以前的值来实现。
进程切换涉及到状态变化,比模式切换需要做更多的工作,显然,模式切换与进程切换是不同的。
发生模式切换可以不改变正处于运行态的进程状态,在这种情况ixa,保存上下文和以后恢复上下文只需要很
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 精髓与设计原理第五版 精髓 设计 原理 第五