什么是死锁?
所谓死锁是指多个进程因竞争资源而相互等待,若无外力作用,这些进程都无法向前推进。
二、死锁是怎样产生的?
- 系统资源的竞争 当不可剥得资源的数量不足以满足进程的需要时,使得进程会因为争得资源而陷入僵局
- 进程推进顺序不当 进程在运行过程中,请求和释放资源的顺序不当,也会造成死锁。例如并发进程P1,P2
分别保持了资源R1,R2,而进程P1申请R2,同时进程P2申请R1
- ,两者都会因为所需资源被占而阻塞。信号量使用不当也会造成死锁。
三、死锁产生的条件
产生死锁必须满足以下四个条件,缺一不可:
- 互斥条件 一个资源只能被一个进程所占用,此时若其它进程请求该资源,则请求进程必须等待
- 不剥得条件 进程使用的资源在未完成使用之前,不能被其它进程强行得走。
- 请求和保持条件 一个进程因为请求资源而阻塞时,对已获资源保持不放
- 循环等待条件 若干进程形成了一种头尾相接环状等待资源的关系
四、死锁的处理策略
- 预防死锁 破坏死锁产生的四个必要条件之一
- 避免死锁 在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而避免死锁
- 死锁检测及解除 通过系统检测机构及时的检测出死锁的发生,然后采取某种策略解除死锁
1)死锁预防
死锁预防就是破坏死锁产生的四个条件之一。
- 破坏互斥条件 有些资源根本不能同时访问,如打印机,所以破坏互斥条件而预防死锁的方法一般不太可行。
- 破坏不可剥得条件 当一个保持了某些不可剥得资源的进程,请求新的资源而得不到满足时,它必须释放已经保持的资源,待以后需要时再申请。这就意味着一个进程已占有的资源会被暂时释放掉或者说是被剥得了。特点:释放已获得资源可能会造成前一段工作失效,实现复杂、降低了系统吞吐量。
- 破坏请求和保持条件 这种策略要求进程在申请资源时,它不能占有其他资源,也就是需要进程在执行前一次性申请并获得所有的资源。这种特点是:资源利用率低(资源已分配,但长时间未使用),可能发生讥饿现象(一个进程需要多个常用资源,可能会永久等待,因为它需要的资源至少有一个已经分配给其它进程)
- 破坏循环等待条件 该策略需要对所有的资源进行排序,要求每个进程必须按照递增顺序来申请资源。这种方法问题是编号必须相对稳定,这就限制了新类型的增加...(还没写完)
2)死锁避免
死锁避免方法中,允许进程动态的申请资源,但是系统进行资源分配之前,应该先计算此资源的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程,否则让进程等待。
系统安全状态 所谓安全状态是指系统能够按照某种进程推进的顺序(P1,P2,...,Pn
)为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可以胜利的完成。此时称(P1,P2,...,Pn)是安全序列。如果系统无法找到一个安全序列,则系统处于不安全状态。需要注意的是并非所有的不安全状态都是死锁状态,但当系统进入不安全状态后,便可能进入死锁状态;反之,只要系统处于安全状态,系统便可以避免进入四锁状态。
临界区
虽然多个进程可以共享系统资源,但是其中许多资源一次只能被一个进程使用,这种资源称为临界资源。将每一个进程访问临界资源的那段代码称作临界区,为了保证临界资源正常使用,可以把临界资源访问分为四个部分:
- 进入区 进入区检查当前代码是否可以进入临界区,如果可以进入临界区,则应该应该设置正在访问临界区的标志,以阻止其它进程同时进入临界区。
- 临界区 指进程访问临界资源的那段代码。
- 退出区 将正在访问临界区的标志清除。
- 剩余区 代码中的其余部分。
为避免两个进程同时进入临界区,同步机制应该遵寻以下准则:
- 空闲让进 临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区
- 忙则等待 当已有`进程进入临界区时,其它试图进入临界区的进程必须等待
- 有限等待 对请求访问的进程,应该保证能在有限时间内进入临界区
- 让权等待 当进程不能进入临界区时,应立即释放处理器,防止进程忙等待。
区分同步和互斥: 同步称作直接制约关系,它是指为了完成某种任务而建立的2个或者多个进程,这些进程因为要在某些位置上协调工作次序而等待、传递消息所产生的制约关系。例如:写进程A通过单缓冲区向读进程B提供数据。当缓冲区为空时,进程B因为不能获得数据而阻塞,一旦进程B将数据写入缓冲区,进程B被唤醒,反之,当缓冲区满时,进程A被阻塞,仅当B取走缓冲区数据时,才唤醒A。 互斥称作间接制约关系,它指当一个进程进入临界区时空,另一个进程必须等待,当它退出临界区时,另一个进程才允许访问临界区。例如有一台打印设备,有两个进程A和B,如果A需要打印时,系统已经将打印机分配给B,则进程A必须阻塞,一段进程B将打印机释放,系统便唤醒进程A,并将其阻塞状态变为就绪状态。
长期调度程序和短期调度程序
批处理系统中进程更多的被提交而不是马上执行。这些程序放在大容量存储设备的缓冲池中。长期调度程序(作业调度程序)从该缓冲池中选择进程并装入内存准备执行。
短期调度程序(CPU调度程序)从准备执行的进程中选择进程,并为它分配CPU。这两个调度程序的主要差别是他们的执行频率。一般I/O为主的进程比CPU为主的进程执行时间更长,长期调度程序应该合理的选择以I/O为主和CPU为主的组合进程。二、进程调度的方式
所谓进程调度方式是指当某一个进程正在处理机上运行时,若有某个更为紧迫、重要的进程需要处理,即为有优先级别更高的进程进入队列,此时该如何分配处理机。通常有两种调度方法:
- 非抢站式(非剥得式)调度 指当一个进程在处理机上运行时,即使有某个更为重要、紧迫的进程进入就绪队列,仍然让正在执行的进程继续执行,直到它执行完或者阻塞时才把处理机分配给更为紧迫、重要的进程
- 抢占式(剥得式)调度 指当一个进程在处理机上运行时,即使有某个更为重要、紧迫的进程进入就绪队列,则立即暂停正在执行的进程,并将处理机分配给更为紧迫、重要的进程
两种调度方式的比较: 非抢占式调度方法的优点是实现简单、系统开销小、适用于大多数的批处理程序,但是不可以用于分时系统和大多数的实时系统。采用抢占式调度方法可以提高系统的吞吐率和响应效率,但是必须遵寻一定的原则:优先权、短进程优先等。
三、进程调度准则
不同调度算法具有不同的特性,在考虑调度算法的性能时,需要基本准则进行评价:
- CPU利用率
- 系统吞吐量
- 周转时间
- 等待时间
- 响应时间
四、调度算法
- 先来先服务(FCFS)调度算法 该算法用于作业调度也可用于进程调度,FCFS算法属于非抢占调度算法,主要特点是:算法简单、但效率底,对长作业有利,而不利于短作业。
- 短作业优先(SJF)调度算法 短作业优先调度算法是指对段作业(进程)优先调度的算法。SJF也有以下特点:
- 该算法对长作业不利,可能使得长作业长期不被调度,出现讥饿现象。
- 该算法完全没有考虑作业的紧迫程度,因而不能保证紧迫性的作业被及时处理。
- SJF调度算法的平均等待时间和平均周转时间最少。
- 优先级调度算法 在作业调度中,优先级调度算法每次从后备作业队列中选择优先级别最高的一个或者几个将他们装入内存,并分配资源创建进程放入就绪队列。在进程调度中,优先级调度算法从就绪队列中选择优先级别最高的进程,为其分配处理机,使之运行。根据调度方式,可以将优先级调度算法分为:
- 非抢占式优先级调度算法。
- 抢占式优先级调度算法。
- 时间片轮转调度算法 时间片轮转算法主要用于分时系统。进程调度算法按照先到先服务的规则选择就绪队列的第一个进程执行,但是仅能执行一个时间片,当使用完时间片后,即使进程没有完成运行也必须释放CPU,返回到就绪队列的尾部。该算法主要特点是时间片的长短对系统性能影响很大:
- 如果时间片比较长,则时间片轮转调度算法就退化为FCFS调度算法。
- 如果时间片比较短,那么处理机将在进程间过于频繁的切换,系统开销很大。
多级队列调度算法 它将就绪队列分为多个独立的队列,例如系统进程队列、交互进程队列...。根据进程属性,一个进程被永久的分配到一个队列中,每个队列都有自己的调度算法。另外,队列之间必须有调度,通常采用固定优先级抢占调度。每个队列与更低层队列相比具有绝对的优先级。每个进程永远只在一种队列中,这种调度的优点是低调度开销,缺点是不够灵活。
多级反馈队列调度算法 它的主要思想是根据不同的CPU区间特点来区分进程,如果进程使用过多的CPU时间,那么他会被转移到更低优先级队列,此外在较低优先级队列中等待时间较长的进程会被移动到更高优先级队列。这种调度方式可以阻止讥饿的发生。
一、进程
1. 进程的概念
“进程”是操作系统的最基本、最重要的概念之一。但迄今为止对这一概念还没有一个确切的统一的描述。下面是三个典型的定义:
- 进程是程序的一次执行
- 进程是一个程序及其数据在处理机上顺序执行所发生的活动
- 进程是一个具有独立功能的程序在一个数据集合上运行的过程,它是系统进程资源分配和调度的一个独立单位
2. 进程控制块PCB
系统利用PCB来描述进程的基本情况和运行状态,PCB包含了与一个特定进程相关的信息,他们包括:
- 进程状态
- 程序计数器
- CPU寄存器
- CPU调度信息
- 内存管理信息
- 记账信息
- I/O状态信息
3. 进程的特征
- 动态性 进程是程序的一次执行,它有创建、活动、阻塞、终止等过程,具有一定的生命周期,是动态的产生变化和消亡的。动态性是进程最基本的特征。
- 并发性 指多个进程实体能在一段时间内同时运行。进程的并发性提高了系统资源利用率。
- 独立性 指进程是一个独立运行、独立获得资源、和独立接受调度的基本单位。未建立PCB的程序不能作为一个独立单位。
- 异步性 由于进程的相互制约,使进程具有执行的间断性,即进程按照各自独立的不可预知的速度向前推进。所以在操作系统中需要配置进程同步机制。
- 结构性 每个进程都配置一个PCB进行描述。进程实体是由程序段、数据段、和PCB组成。
4. 进程的状态及其转换
进程状态
通常一个进有5中状态:
- 创建 进程正在被创建,尚未转到就绪状态 。
- 就绪 进程在就绪队列中,等待分配处理器。
- 运行 进程正在处理机上运行。
- 阻塞(等待) 进程在等待某个事件的发生(如I/O完成或受到信号)。
- 终止 进程完成执行。
注意区分就绪状态和等待状态:就绪状态是指进程仅缺少处理机,只需要获得处理机资源就可以运行。而等待状态除了处理机资源外还需要其它资源或等待某一个事件的发生(如I/O请求)。
五种进程状态的转换
- 就绪态 --> 运行态 处于就绪态的进程获得CPU资源
- 运行态 --> 就绪态 处于运行态的进程时间片用完后让出CPU资源,然后退出到就绪态
- 运行态 --> 阻塞态 当进程请求某资源分配或者等待某事件发生(I/O)时,从运行态转换为阻塞态
- 阻塞态 --> 就绪态 当进程等待的时间到达时,如I/O操作结束等,中断处理程序将进程从阻塞态转换为就绪态
共享内存 在通讯的进程间有一块可以直接访问的共享内存,通过这块共享内存的读写操作来实现进程间的信息交互。须要使用同步互斥工具控制数据的读写。
优点:共享内存是最快的IPC方法,仅在建立共享内存的时需要系统调用(内核参与),之后所有的访问被当作常规的内存访问,不需要内核的参与。
消息传递 在消息传递系统中,进程间的数据交换是以格式化的消息(Message)为单位的。它使用操作系统提供的消息传递方法实现进程通讯。进程通过系统提供的发送消息和接受消息原语来进行信息交换。
优点:消息传递对于交换次数较少的数据很有用,因为不需要避免冲突,但是需要内核频繁的参与,速度不如共享内存快。
管道 所谓管道就是一个连接读进程和写进程以实现他们间信息的一种共享文件,又称作pipe文件。向管道中输入的写入进程 以字符流的形式将数据写入管道,接收进程从管道中读数据。管道机制必须提供以下三方面协调能力:互斥、同步、确定对方存在
二、线程
1、线程概念
线程最直接的理解就是一个轻量级进程(LWP),它是一个基本的CPU执行单元,它由线程ID、程序计数器、寄存器集合、堆栈组成。线程是进程的一个实体,它是系统调用和分配的基本单位。线程可以和它同属一个进程的其它线程共享进程资源。线程有就绪、阻塞、运行三种状态。
2、线程与进程的比较
- 调度 在传统操作系统中,拥有资源和独立调度的基本单位是进程。在引入线程的操作系统中,线程是独立调度的基本单位,进程是拥有资源的基本单位。
- 拥有资源 进程是资源拥有的基本单位,而线程不拥有系统资源(只有一点必不可少的资源),但线程可以访问隶属进程的系统资源。
- 并发性 在引入线程的操作系统中,进程和线程都可以并发执行,使得操作系统具有更好的并发性。
- 系统开销 创建或者撤销进程,系统都要为其分配和回收资源,因此操作系统所付出的开销远远大于创建、撤销线程。同样的在进程切换时,操作系统需要保存当前进程的信息并恢复下一个进程的信息,而线程切换只需要保存和设置少部分寄存器内容,开销小。此外属于同一进程的多个线程共享地址空间,这样的话线程间的同步和通信容易实现,甚至无需操作系统的干预。
- 地址空间和其它资源 进程间的地址空间相互独立,属于同一进程的线程之间共享进程资源,某进程内的线程对其它进程不可见。
- 通讯方面 进程间的通讯需要进程同步和互斥手段来辅助,而线程可以直接通过读/写进程数据段(如全局变量 )来进程通讯。
3、为什么线程的提出有利于提高系统的并发?
线程切换的开销小,在线程切换时可能发生进程切换,也可能不发生,这样平均下来每次切换的开销就小啦。
4、线程实现
线程实现分两类:用户线程、内核线程:
- 用户线程 有关线程的管理工作都由应用程序完成,内核意识不到用户线程的存在。应用程序可以通过线程库设计成多线程程序。
- 内核线程 内核线程的所有管理工作由内核完成,应用程序没有线程管理的代码,只有一个到内核线程的编程接口。
5、多线程模型
- 多对一模型 多对一模型将多个用户线程映射到一个内核线程。优点:线程管理是由线程库在用户空间进行的,因而效率比较高。缺点:如果一个线程执行了阻塞系统调用,那么整个进程就会阻塞。
- 一对一模型 一对一模型将每个用户线程映射到一个内核线程。优点:当一个线程被阻塞后,允许另一个线程继续执行,所以并发能力较强。缺点:每创建一个用户级线程都需要创建一个内核级线程与其对应,这样创建线程的开销比较大,会影响到应用程序的性能。
- 多对多模型 多对多模型将n
- 个用户级线程映射到m个内核级线程上,要求内核线程个数m小于等于用户线程n
- 。特点:在多对一模型和一对一模型中取了个折中,克服了多对一模型的并发度不高的缺点,又克服了一对一模型的一个用户进程占用太多内核级线程,开销太大的缺点。又拥有多对一模型和一对一模型各自的优点,可谓集两者之所长。
6、线程池
线程池主要思想是在进程开始时创建一定量的线程,并放入池中以等待工作。当服务器收到请求时,他会唤醒池中的一个线程,并将要处理的请求传递给它。一旦线程完成服务,他会返回池中等待工作。如果池中没有线程,那么服务器会等待到有空线程为止。线程池有以下优点:
- 通常用现有的线程处理请求比等待创建的线程要块。
- 线程池限制了在任何时候可以使用线程的数量。这对那些不支持大量并发线程的系统非常重要。
分类: 操作系统基础
5、进程间通信方式