操作系统 第2章节 进程,线程和作业
一:多道程序设计
1-多道程设计的目的
for:提高吞吐量(作业道数/处理时间),我们可以从提高资源的利用率出发
2-单道程序设计缺点:
设备的利用率低,内存的利用率低,处理机的利用率低
比如CPU去访问内存,CPU空转.内存等待CPU访问也是没有任何操作的.要是有多个东西要去访问不冲突的设备,单道就只有一个一个的等(明明可以直接同时访问的)
通过多道程序处理
中间的CPU等待访问设备A的时候,可以处理程序B,同时允许多个不冲突的设备同时访问
3-多道程序设计的道数的选择:
最好与系统资源数量相当.因为:如果过少,系统资源利用率低,如果过多,系统调度等等的开销过大
4-随着多道程序设计的思想到来,同时也带来了许多问题:
1:如果程序个数多于处理机数量,应该如何分配
2:存储资源的管理应该如何处理,比如:存储器地址的独立性or共享性?内存外存交换的分配和去配?相对地址和绝对地址的地址转换?
3:设备资源如果分配,比如:分配机制,IO控制等等
二:进程的引入
在多道程序系统中,一个程序是:推进,暂停,推进,暂停的
暂停:需要我们保存现场(PSW+PC,REG)然后跳转到目标位置
推进:恢复现场(REG,PSW+PC)然后跳转到目前的地址
1:进程的概念:
可参与并发执行的程序,进程是具有一定独立功能的程序关于一个数据集合的一次运行活动
(强调了并发和运行):注意哦,不是并行(微观也是同时,要求多CPU),是并发(宏观同时,微观交替)
2:进程状态和状态的转换
运行态:占用CPU中
就绪态:可以运行,等待CPU
等待态:等待某一个时间的发生
就绪->运行:获得CPU
运行->就绪:被剥夺CPU
运行->等待:申请资源,但是还没有送到
等待->就绪:得到资源
当然用户感受不到上面的转换过程
3:进程控制块
是程序的静态描述
有着:进程的
描述信息:
-:进程标识:pid
-:所属用户uid
进程的控制信息:
CPU,磁盘,网络流的使用情况
当前的进程状态
进程占有的资源信息:
在使用那些文件
在使用那些内存区域
在使用那些IO设备
处理机相关信息:PSW ,PC reg的值
4:进程的组成和上下文
组成:PCB+程序(代码+数据+堆栈)
进程上下文:
进程的物理实体和支持进程运行的物理条件是指进程上下文:
包括:PCB+程序,
环境系统:地址空间,系统栈,打开文件表,地址映射寄存器,通用寄存器,PSW+PC
上下文切换:
由一个进程的上下文切换到另外一个进程的上下文
系统开销:
运行操作系统完成系统管理工作所花费的时间和空间
5.进程的组织
链接形式
进程控制块(PCB)以队列形式组织,队列类型不限于单向或双向,也不一定遵循FIFO原则。
就绪队列:系统可包含一个或多个就绪队列
等待队列:每个等待事件对应一个独立的等待队列
运行指示字:每个处理机配备一个运行指示字
索引方式
执行指针:指向当前正在执行的进程块
就绪表指针:指向存储就绪态PCB的就绪索引表
阻塞表指针:指向存储阻塞态(等待)PCB的阻塞索引表
6:进程的类型与特征
分为系统进程,用户进程
系统进程:运行操作系统程序,完成系统管理功能.
系统启动后一直存在直到系统的关闭,执行一个无限的循环
管态,执行所有指令,优先级高于用户进程
用户进程:为用户服务,不一定用户自己写的
特征:
--:并发性:可以和其他进程一起推进
--:动态性:动态的产生,消亡,等待等等
--:独立性:单独的调度1单元
--:交往性:可以和其他进程交互
--异步性:可以格子独立,不可预知速度的推进
--:结构性:每个进程只有一个PCB
7:进程间相互联系和相互作用
联系:
相关进程:同一家族的进程,可以共享文件,需要相互同学,协调推进,(父进程可以监视子进程,子进程完成父进程提供的任务)
无关进程:没有逻辑关系,同时执行,但是有资源的竞争,互斥,死锁,饿死的问题
作用:
直接相互作用:发生在相关进程之间,有意识,无中间媒介
间接相互作用:发生在任何的进程之间,有媒介
8:进程的创建和撤销
创建的时候,需要分配内存+加载程序_入就绪队列
撤销的时候:需要去配资源,撤销PCB,通知父进程(有可能是正常的终止,指发生了地址越界偶然非法指令or 被kill)
(除了初始进程,其他的进程都是被父进程创建并形成家族的)
如果考虑创建和撤销这两个状态,正常的进程的状态转移图:
9:进程与程序的联系和差别:
差别
1-程序(代码段,数据结构集)是静态的,是长期存放在磁盘的可执行文件,是一系列指令集合
2-进程是动态的,是程序的一次执行过程,有生命期
3-一个进程只能执行一个程序,一个程序可以被多个进程执行
联系:
进程包括一个程序,进程就是程序的几个运行
10.UNIX进程
PROC结构:保存的信息无论当进程在内存还是外存都是需要的
USER结构:内存中才是需要的,也可以和进程的程序一起移动到外存
-创建子进程
PID=fork() //子进程是父进程的复制品,返回值是父进程为子进程的编号,子进程为0
-加载并执行新的程序
execl(prog,arg0,arg1......,)
后面的argx为参数,执行prog
-:撤销
exit(Status) //Status为终止态, 然后唤醒父进程
-Abort终止进程
被终止子进程的父进程执行该指令.
可能因为:子进程使用资源过多or子进程任务超时or父进程退出OS,那么子进程也被禁止(但是在UNIX,子进程会以init为新的父进程)
当然也可以是kill来终止
pid=wait(&Status) //返回的是终止的子进程的PID,参数是子进程的终止状态
使用程序描述:
main()
{
int pid1,pid2,pid3,pid4,pid5,pid6,pid7,pid8;
int end_p1=end_p2=end_p3=end_p4=end_p5=…=end_p8=0;
int pid, status;
if((pid1=fork())= =0) execl("P1",0);
wait(&status);
if((pid2=fork())= =0) execl("P2",0);
if((pid3=fork())= =0) execl("P3",0);
if((pid4=fork())= =0) execl("P4",0);
do{ //等待P2结束
pid=wait(&status);
if(pid= =pid2) end_p2=1;
if(pid= =pid3) end_p3=1;
if(pid= =pid4) end_p4=1;
}while(end_p2= =0);
if((pid5=fork())= =0) execl("P5",0);
if((pid6=fork())= =0) execl("P6",0);
do{ //等待P3和P6结束
pid=wait(&status);
if(pid= =pid3) end_p3=1;
if(pid= =pid4) end_p4=1;
if(pid= =pid5) end_p5=1;
if(pid= =pid6) end_p6=1;
}while(end_p3= =0||end_p6= =0);
if((pid7=fork())= =0) execl("P7",0);
do{ //等待P4,P5,P7结束
pid=wait(&status);
if(pid= =pid4) end_p4=1;
if(pid= =pid5) end_p5=1;
if(pid= =pid7) end_p7=1;
}while(end_p4= =0||end_p5= =0||end_p7= =0);
if((pid8=fork())= =0) execl("P8",0);
wait(&status);
exit(0);
}
11.vfork和fork
fork:复制地址空间(code,data,stack)和控制结构(proc,user)
特点:父进程和子进程都有独立的数据拷贝
问题:不加载新的程序:不能数据共享,不能描述有解缓冲区
加载程序:复制可能没有意义,浪费空间
vfork:只复制了控制结构(proc+user),不复制地址空间
特点:
父进程和子进程共享地址空间
子进程可以使用execve改变其的虚拟地址空间
三:线程和轻进程
1.线程的引入:
为什么需要引入线程尼?
进程的切换需要上下文切换,但是内容太多了(PCB+程序+系统环境:地址空间,栈空间,文件表),开销太大了,而且一个进程可能也有很多个事情需要同时的去做,但是传统的进程不能够很好的去表达这些关系(没有良好的耦合关系),通讯也十分麻烦
所以就引入了线程,允许一个进程有多个线程,线程的上下文切换只涉及了reg和用户栈,而且线程之间的通讯也会更加的方便.
2.线程的概念:
概念:进程中的一个相对独立的执行流.
进程vs线程:
进程是资源的分配单位.
线程是执行的单位
多线程开发的优点:
-上下文切换快(地址空间不变)
-系统的开发小
-相关线程间的通讯容易(共享数据空间)
3.线程的结构:
下面是进程的:
下面是线程的:
4.线程控制块:
TCB:标志着线程存在的数据结构,其中包含了对线程管理所需要的全部信息
(包括了:线程标识,现场状态,调度参数,现场(通用寄存器,PC,SP),链接指针)
存放在对应的级别的空间:
用户线程:目态空间
核心线程:系统空间
5.线程的实现:
用户级线程ULT:
特点:
-基于library函数创建,系统不可见
-线程的创建,撤销,状态转换都发生在目态(TCB在用户空间)
-TCB在用户空间,一个进程一个系统栈
-进程的状态复杂
优点:
-不依赖操作系统,调度灵活
-同一进程中多线程切换快(不切换地址空间,共享数据空间)
缺点:
-同一个进程的线程不是真正的并行
-一个线程受阻,进程的其他线程阻塞
核心级线程KLT:
特点:
-基于系统调用实现
-创建,撤销和状态的转换由操作系统完成(TCB在系统空间)
-线程是CPU调度的基本单位,进程的状态没有意义
优点:
-同一个进程的多线程可以并行的执行
-一个现场进入核心等待,其他的进程可以执行(多CPU)
缺点:
-系统的开销大,同一个进程的多线程切换慢
-调度由系统实现,调度算法不够灵活
混合线程:
结构:
6.线程的应用:
-处理内在由多控制流,有合作,需要数据共享的背景
-多线程优于多进程(切换上下文数量级差100倍)
-提高处理机和设备的并行性
-多处理机环境适合多线程的运用
例子:
对于一个IDE,一个线程用于检查代码的语法逻辑,一个用于渲染代码不同意义的字体颜色,一个实现定时时钟的定时保存
再比如一个WEB server请求,直接pop up 一个线程让其去处理就好了
7.java线程:
四个状态:
New:新创建的线程
Runnable:可运行状态
Blocked:封锁状态
Dead:终止状态
JVM:
java虚拟机:处于java和操作系统之间,做到了java的良好的跨平台性质
java线程与操作系统线程之间的对应关系由JVM确定
四:作业
1.作业的概念:
用户要求计算机系统为其完成的计算任务集合
2.作业步:
作用处理过程中一个相对独立的步骤,一般一个作业步可由一个进程完成,某些作业步之间可以实现并行.
3.作业控制块:
表示作业存在的数据结构其中包含系统对作业管理所需要的全部信息:作业名称,作业状态,调度参数,资源需求,相关进程,作业长度,在输入井和输出井中的存放位置,记账信息
作业的分类:
批处理作业和交互式作业
-作业控制语言(JCL):描述批处理作业控制意图的语言
-作业说明书(JCL语句的序列):一般一个特殊符号起始
-作业控制程序:解释并处理作业说明书的程序
-作业控制进程:执行作业控制程序的进程
批处理作业:
-1:作业由假脱机输入程序输入到输入井
-2:经过OS的调度程序选中后进入内存
-3:同时由作业调度程序为其建立作业控制进程,执行作业控制程序
-4:作业控制进程解毒读作说明书的语句,并且根据作业步的要求建立对应的进程
交互式作业:
账户管理:
/etc/passwd文件(用户名,口令,用户根目录,同组用户,余额)
操作:
创建:由用户提供,or系统建立
撤销:删除用户目录机器对应的文件,在passwd中删除对应的entry
注册:
login:用户名
password:***
使用...
注销:
显式注销:logoff or 隐式注销(无操作)
作业
总结:作业进入内存后变为进程进行执行,一个作业一般有多个进程,一个进程一般又会划分为一个偶or多个线程进行执行(如果不支持的话就会单线程执行)