计算机操作系统——进程管理
Table of Contents
进程与线程
1.进程
进程是资源分配的基本单位。
进程控制块(Process Control Block, PCB)描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对PCB的操作。
下图显示了4个程序创建了4个进程,这4个进程可以并发地执行。
2.线程
线程是独立调度的基本单位。
一个进程中可以有多个线程,它们共享进程资源。
3.区别
- 拥有资源
- 进程是资源分配的基本单元,但是线程不拥有资源,线程可以访问隶属进程的资源。
- 调度
- 线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程的切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
- 系统开销
- 由于创建或撤销进程时,系统都要为止分配或回收资源,如内存空间、I/O设备等,所符出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程CPU环境的保存及新调度进程CPU环境的设置,而线程切换时至需要保存和设置少量寄存器内容,开销很小。
- 通信方面
- 线程间可以直接读写统一进程中的数据进行通信,但是进程通信需要借助IPC.
进程状态的切换
- 就绪状态(ready):等待被调度
- 运行状态(running)
- 阻塞状态(waiting):等待资源
需要注意的是:
- 只有就绪和运行状态可以相互转换,其他的都是单向转换。就绪状态的进程通过调度算法从而获得CPU时间,转为运行状态;而运行状态的进程,在分配给它的CPU时间片用完之后就会转为就绪状态,等待下次调度。
- 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括CPU时间,缺少CPU时间会从婞状态转换为就绪状态。
进程调度算法
不同环境的调度算法目标不同,因此需要针对不同环境来讨论调度算法。
1.批处理系统
批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)
- 先来先服务first-come first-servered (FCFS)
- 非抢占式的调度算法,按照请求的顺序进行调度
- 有利于长作业,不利于短作业,因为短作业必须一致等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
- 短作业优先 shortest job first (SJF)
- 非抢占式的调度算法,按估计运行时间最短的顺序进行调度。
- 长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
- 最短剩余时间优先 shortest remaining time next (SRTN)
- 最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进行。否则新的进程等待。
2.交互式系统
交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。
- 时间片轮转
- 将所有就绪进程按FCFS的原则排成一个队列,每次调度时,把CPU时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把CPU时间分配给队首的进程。
- 时间片轮转算法的效率和时间片的大小有很大的关系:
- 因为进程切换都要保存进程的信息并且载入进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。
- 而如果时间片过长,那么实时性就不能得到保证。
- 优先级调度
- 为每个进程分配一个优先级,按优先级进行调度。
- 为了防止低优先级得进程永远等不到调度,可以随着时间得推移增加等待进程的优先级。
- 多级反馈队列
- 一个进程需要执行100个时间片,如果采用时间片轮转调度算法,那么需要交换100次。多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不相同。进程在第一个队列没执行完,就会被以到下一个队列,在这种方式下,之前的进程只需要交换7次。
- 每个队列的优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。
- 可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。
3.实时系统
实时系统要求在一个请求在一个确定的时间内得到响应。
分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
进程同步
1.临界区
对临界资源进行访问的那段代码称为临界区。
为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
2.同步与互斥
同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后执行关系。
互斥:多个进程在同一时刻只有一个进程能进入临界区。
3.信号量
信号量(Semaphore)是一个整型变量,可以对其进行down和up操作,也就是常见的P和V操作。
- down:如果信号量大于0,执行-1操作;如果信号量等于0,进程睡眠,等待信号量大于0;
- up:对信号量执行+1操作,唤醒睡眠的进程让其完成down操作。
down和up操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
如果信号量的取值只能为0或者1,那么就成为了互斥量(Mutex),0表示临界区已经加锁,1表示临界区解锁。
4.管程
管程有个一重要特性:在一个时刻只能有一个进程使用管程。进程无法继续执行的时候不能一直占用管程,否则其它进程永远不能使用管程。
管程引入了条件变量以及相关的操作:wait()和signal()来实现同步操作。对条件变量执行wait()操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal()操作用于唤醒被阻塞的进程。
进程通信
进程同步和进程通信很容易混淆,它们的区别在于:
- 进程同步:控制多个进程按一定的顺序执行;
- 进程通信:进程间传输信息。
进程通信是一种手段,而进程同步是一种目的。也可以说,为了达到进程同步的目的,需要让进程间进行通信,传输一些需要进程同步所需要的信息。
1.管道
管道是通过pipe函数创建的,fd[0]用于读,fd[1]用于写。
#include <unistd.h>
int pipe(int fd[2]);
它具有以下线程:
- 只支持半双工通信(单向交替传输) ;
- 只能在父子进程或者兄弟进程中使用。
2.FIFO
也称命名管道,去除了管道只能在父子进程或兄弟进程中使用的限制。
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
FIFO常用于客户-服务器应用程序中,FIFO用作汇聚点,在客户进程和服务器进程之间传递数据。
3.消息队列
相比于FIFO,消息队列具有以下优点:
- 消息队列可以独立于读写进程存在,从而避免了FIFO中同步管道的打开和关闭时可能产生的困难;
- 避免了FIFO的同步阻塞问题,不需要进程自己提供同步方法;
- 读进程可以根据消息类型有选择地接收消息,而不像FIFO那样只能默认地接收。
4.信号量
它是一个计数器,用于为多个进程提供对共享数据对象的访问。
5.共享存储
允许多个进程共享一个给定的存储区,因为数据不需要在进程之间复制,所以这是最快的一种IPC。
需要使用信号量用来同步对共享存储的访问。
多个进程可以将同一个文件映射到它们的地址空间从而实现共享内存。另外XSI共享内存不是使用文件,而是使用内存的匿名段。
6.套接字
与其它通信机制不同的是,它可用于不同机器之间的进程通信。
下一篇: MYSQL_入门查询