第二部分 进程概念
引入进程的概念
一个操作系统必然是CPU和I/O设备协同工作的一个过程,如下图:
图上表明,当I/O闲置时,CPU高速工作,而当I/O变为高电平启动时,CPU先等待然后等I/O设备启动后,CPU继续完成其他的工作。这一定程度上造成CPU的使用效率达不到100%。
最理想的多任务模型
一个理想情况:
现在内存里有两个程序A和B。由电平上看,A,B程序也是一会执行CPU指令,一会执行I/O指令。但如果搭配得当,使得A程序执行CPU指令时,B程序执行I/O指令,协同搭配,就可以提高CPU的使用效率,使得其不再等待。
进程
进程概念
An operating system executes(执行) a variety of programs:
- Batch system - jobs
- Time-shared systems - user programs or tasks
为什么不能把程序称之为进程
- different data with same program
- different program with same data
上面两种实际上都是两个进程。
进程定义
Process - a program in execution;process execution must progress in sequential fashion
进程有三个维度的要素:
1.是正在执行的程序
2.进程执行的程序正在处理数据
3.进程的状态。静止的程序是不运行的程序,但它不是一个进程。
进程状态迁移实例:
- 有五个基本状态:new,ready(一切准备就绪,只要CPU给指令就可以执行),waiting(进程还未准备好),running,terminated(进程结束执行).
PCB(进程控制块)
每一个进程都有一个PCB,是在内存里面驻留的一对一的,反映相应进程信息。
进程通常与下列信息关联:
- Process state
- Process number,进程号,必须严格控制每个进程号不同,是一个正整数。
- Program counter(计算机中提供要从存储器中取出的下一个指令地址的寄存器)
- CPU registers
- CPU scheduling information
- Memory-management information
- Accounting information
- I/O status information
- THAT SPECIFIC TO THE PROCESS(不会放到程序中去)
进程管理:
总的来讲,一个进程由一个PCB块来控制。而进程主要有三个状态:就绪状态,等待状态和执行状态。三种状态分别拉成链表中队列的形式,里面分别有head指针和tail指针。
我们可以把他们看成就绪队列,等待队列和执行队列。
- 就绪的进程全部放入一个队列中。这样的好处是当我要执行就绪进程时我只需要关注这个队列里的进程就可以了,其他的进程可以一概不管。
- 执行队列。假设只有单核CPU的状态下,则只有一个进程或没有(CPU空闲)在执行。
- 等待队列。比较直观的设计是,在等待同一个资源进程的时候,这些进程组成一个队列。如图tape,disk,terminal三种不同资源组成三个队列。
思考:操作系统的管理实际就是把PCB从一个队列放入另外一个队列(迁移)。相当于是管理不同的进程队列。
进程调度队列,动态反应操作系统全貌
- Job queue — 等待进入计算机系统的待处理任务
- Ready queue — 驻留内存,准备就绪,等待CPU
- Device queues — 等待I/O设备的进程队列
进程是如何在队列中迁移的
- 这个图强调Ready queue,当进程拿到CPU后,进程离开Ready queue,进入执行队列。执行进程不可能一直占用CPU,因为程序本身除了要执行,还需要执行I/O操作。当执行I/O操作时,它需要被转移到其他的I/O请求的队列里去,从而与外部设备进行连接(如第二行),当做完I/O操作以后,继续进入ready queue。
- time slice expired为时间片,它可以强制剥夺进程的CPU使用权(时间片用完)。但之后由于它拥有资源,所以还会立马转入ready queue等待下一次获取CPU。
- 第四行则为一个进程创建了一个子进程。等子进程做完以后,才可以唤醒进程。它有一个等待状态。它等待的资源不是I/O资源,而是等待子进程结束。
- 第五行为进程需要等待一个中断信号产生。中断信号发生,则可以进入ready queue。
进程上下文切换(Context Switch)
- CPU任何时候只能为一个进程服务
- 当CPU转向为另一个进程服务时,由于CPU内部资源(内部寄存器)有限,它必须保存原有(转换前)进程的状态,装入待服务(转换后)进程的状态,也即“进程上下文切换”
- “状态”指寄存器、标志位、堆栈等当前值。
- 上下文切换时间是一种额外开销(overhead),因为期间CPU不做对用户进程直接有益的事。
- 上下文切换时间决定于CPU硬件支持力度。
进程操作
进程创建
- 父进程创建若干子进程,后者再创建其子进程,以此类推,构成了反映“传承”关系的一颗进程树。进程的运行实际上就是进程树的运行。
- 子进程的资源分配类型
1.子进程共享父进程的所有资源(UNIX)
2.子进程共享父进程的部分资源
3.子进程不从父进程共享资源,重新独立申请 - 执行代码的执行顺序
1.父进程和子进程并发执行
2.父进程在子进程执行期间等待,待子进程执行完毕后才恢复执行余下代码
创建进程分三步:
1.申请PCB空间,分配一个指向PCB的指针。
2.申请一个唯一的PID号即进程号。
3.对PCB空间每一个单元赋值。
以UNIX为例进行进程创建
地址空间中的image
- 子进程Duplicate父进程的image。
解释一下Duplicate:创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
也即Linux中的fork()函数。 - UNIX的进程创建中,fork系统首先先创建一个新的(子)进程,fork之后,exec系统调用装入一个新程序。
- 父进程fork()一个子进程,子进程继承了父进程所有的资源。
- 但往往子进程不想要父进程的资源,所以调用system call函数exec()装进自己新的程序。
- 当子进程发送了exit(),即中止信号返回给父进程,父进程结束wait状态,进入就绪队列。
一个具体代码:
- 代码首先定义Pid类型,此时只有一个进程,定义了一个Pid的局部变量。
- 调用fork()创建子进程。按照Linux的做法,子进程完全继承父进程的一切。子进程和父进程唯一不同的是PID号,同时两个进程相互独立,子进程独立执行execlp()。
- fork()在返回过程中,父进程返回值是一个非0正整数,而这个正整数为子进程的PID号。而子进程的返回值为0,如果出现错误,fork返回一个负值。
- Pid_t pid在子进程不执行。因为父进程已经定义过PID号,子进程无需重新定义。
- 最后一个else父进程调用wait之后会一直阻塞,等待子进程结束,父进程wait一旦返回则表示子进程所有资源已经被回收。
进程终止
进程终止语义之一:
子进程执行完最后一条指令后,要求操作系统将自己弹出(exit)。语义动作含:
- 子进程传递数据给父进程(通过父进程的wait操作)。
- 子进程的资源被操作系统收回。
进程终止语义之二:
父进程终止子进程的执行。有很多原因,一般情况下是子进程没有执行完毕就被终止了。
问题:如果父进程终止了,它的子进程怎么办?
结论:有些操作系统把这些子进程也全部终止(All children terminated - cascading)。
进程间合作
- 独立进程不会影响其它进程的执行,也不被影响。
- 合作进程影响其它进程,或者受其影响。
- 进程间合作是必须的。如共享信息,加速执行任务,模块化,方便调用等。
经典案例:生产者-消费者问题
- 生产者进程“生产”出信息,存储在缓冲区,供消费者进程“消费”。即生产者消费者共享缓冲区。
我们讨论bounded buffer情况,即缓冲区数量有限的情况。此时考虑:
- 如果缓冲区为空,那么消费者无法消费,无法从缓冲区取东西。必须等待。
- 如果缓冲区满了,那么生产者无法生产。生产的东西放不进缓冲区。
故两者需要相互关联。
Interprocess Communication(IPC)
进程间通信IPC,提供一套进程通信、进程同步的机制。
消息系统 — 进程间相互通信的途径,不需要有共享变量的介入。
IPC机制有2个最基本的进程操作:
- send(message)
- receive(message)
变种:
- send(P,message)— 直接发给进程P
- receive(Q,message)— 直接接受来自进程Q的消息。
变种:Indirect Communication
- send(A,message),A是邮件服务器。
- receive (A,message)。
★★同步通信VS异步通信
同步通信:
- 发送操作send:发送进程等待,直至接受进程确认收到消息。
- 接受操作receive:接受进程等待,直至有个消息到达。
异步通信:
- 发送操作send:发送进程发出消息后立即返回,该干什么干什么,不理会消息是否送达。
- 接受操作receive:接受进程执行一次接受动作,要么收到一条有效信息,要么收到空消息。
举例:TCP/IP
- TCP一个数据包发送以后必须等待接受进程确认收到消息,因此它较为可靠。
- IP包发出去后,立即返回。因此其通信性能好,速度快。
进程之间相互通信表明这些进程为协同进程。