1

特征

并发

并发是指宏观上在一段时间内能够同时运行多个程序,而并行则指同一个时刻能运行多个指令。

并行需要硬件支持,如多流水线或者多处理器。

操作系统通过引入进程和线程,使得程序能够并发运行。

共享

共享是指系统的资源可以被多个并发进程共同使用。

有两种共享方式:互斥共享和同时共享。

互斥共享的资源称为临界资源,例如打印机等,在同一时间只允许一个进程访问,需要同步机制来实现对临界的访问。

虚拟

虚拟技术把一个物理实体转换为多个逻辑实体。

主要有两种虚拟技术:时分复用技术和空分复用技术。

多个进程能在同一个处理器上并发使用时分复用技术,让每个进程轮流占有处理器

异步

异步指进程不是一次性完成的,而是走走停停,以不可知的速度向前推进。

进程管理

进程与线程

进程

进程是资源分配的基本单位。

进程控制块(Process Control Block,pcb)描述进程的基本信息与运行状态,所谓的创建进程和撤销进程,都是指对PCB的操作。

线程

线程是独立调度的基本单位。

一个进程可以有多个线程,它们共享进程资源。

区别
1、拥有资源

进程是资源分配的基本单位,但是线程不用有资源,线程可以访问隶属于进程的资源。

2、调度
3、系统开销
4、通信

进程调度算法

不同环境的调度算法目标不同,因此需要针对不同环境来讨论调度算法。

批处理系统

批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)

先来先服务

按照请求的顺序进行调度。

有利于长作业,但不利于短作业,因此短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。

短作业先执行

按估计运行时间最短的顺序进行调度。

长作业可能会被饿死,处于一直等待短作业执行完毕的状态。因此如果一直有短作业到来,那么长作业永远得不到调度。

响应比高优先调度算法

是对FCFS和SJF的一种综合平衡,FCFS只考虑作业的等待时间,而SJF只考虑作业的运行时间,这两种方式在极端情况下都会带来不便,HRN调度策略同时考虑每个策略的等待时间跟运行时间,从中选出响应比最高的作业。响应比R = (W + T) / T = 1 + W/T。其中T表示该作业估计得执行时间,W为作业在后备状态队列的等待时间。每当要进行作业调度时,系统计算每个作业的响应比,选择其中的R最大者执行。这样,即使长作业,随着等待时间的增加,W / T也会随着增加,也就有机会调度执行。

交互式系统
优先权调度算法

分为静态优先权跟动态优先权为每个进程分配一个优先权,按照优先权进行调度。为了防止优先级低的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。

轮转法

也叫时间片轮转,将所有就绪进程按FCFS的原则排成一个队列,每次调度时,把cpu分配给首进程,让该进程执行一个时间片。当时间片用完时,由定时器发出时间中断,调度程序便停止该进程的运行,并将它运行送就绪队列的末尾,同时将cpu分配给队首的进程,时间片轮转算法的效率和时间片大小有很大关系,因为进程切换要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花费过多的时间。

进程同步

临界区

对临界资源进行访问的那段代码称为临界区。

为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。

// entry section
// critical section;
// exit section
同步与互斥
  • 同步:多个进程按一定顺序执行。
  • 互斥:多个进程同一时刻只有一个进程能够进入临界区。
信号量

信号量(Semaphore)是一个整形变量,可以对其执行down和up操作,也就是常见的P和V操作。

  • down:如果信号量大于0,执行-1操作,如果信号量等于0,进程睡眠,等待信号量大于0。
  • up:对信号量执行+1操作,唤醒睡眠的进程让其完成down操作。

down和up操作需要被设计成原语,不可分割,通常的做法是执行这些操作时候屏蔽中断。

如果信号量的取值只能0或者1,那么久成为了互斥量,0表示临界区已经加锁,1表示临界区解锁。

管程

管程有一个重要的特性:在一个时刻只能有一个进程使用管程,进程在无法继续执行的时候不能一直占有管程,否则其他进程永远不能使用管程。

管程引入了条件变量以及相关操作,wait()和signal()来实现同步操作。对条件变量执行wait()操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal()操作用来唤醒被阻塞的进程。

进程通信

进程同步跟通信的区别:

  • 进程同步:控制多个进程按照一定顺序执行。
  • 进程通信:进程间传递信息。

进程通信是一种手段,而进程同步是一种目的。也可以说,为了能够达到进程同步的目的,需要让进程进行通信,传输一些进程同步所需要的信息。

管道

管道是通过pipe函数创建的,df[0]用于读,df[1]用于写。

它具有一下限制:

  • 只支持半双工通信。
  • 只能在父子进程中使用。
FIFO

也称为命名管道,去除了管道只能在父子进程中使用的限制。

消息队列

相比于FIFO,消息队列具有以下特点:

  • 消息队列可以独立于读写进程存在,从而避免了FIFO中同步管道的打开和关闭可能产生的困难。
  • 避免了FIFO的同步阻塞问题,不需要进程自己提供同步方法。
  • 读进程可以根据消息类型选择地接收信息,而不像FIFO那样只能默认地接收。
信号量

它是一个计数器,用于为多个进程提供共享数据对象的访问。

共享内存

允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这个最快的一种IPC。

需要使用信号量来同步对共享存储的访问。

多个进程将同一个文件映射到它们的地址空间从而实现共享内存。另外XSI共享内存不是使用文件,而是使用内存的匿名段。

套接字

与其他通信机制不同的是,它可以用于不同机器间的通信。

死锁

产生死锁的主要原因

  • 系统资源不足。
  • 进程运行推进的顺序不当。
  • 资源分配不当等。

死锁的四个必要条件

  • 互斥:每个资源只能同一时间只能给一个进程使用。、
  • 占有且等待:一个进程因请求资源阻塞时,对已有资源保持不放。
  • 不可抢占:进程已获得的资源,在未使用完成之前不能强行剥夺。
  • 循环等待:两个或两个以上进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件就必然成立,而只要上述条件之一不成立,就不会发生死锁。

死锁的解除与预防

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以在系统统计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外也要预防进程处于等待状态得情况下占用资源。因此,对资源的分配要给予合理的规划。

操作系统内存管理

虚拟内存

  • 虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的内存。
  • 为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多块,每块称为一页。这些也被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有的也都必须在物理内存中。当程序引用到不在物理内存的页时,由硬件执行必要的映射,将确实部分装入物理内存并重新执行失败的指令。

用户态跟内核态

内核态跟用户态是操作系统的两种运行级别,intel cpu提供Ring0 - Ring3四种级别的运行模式,Ring0级别最高,Ring3级别最低,其中Ring0是留给操作系统代码,设备驱动代码使用的,它们工作系统和心态;而Ring3则给普通的用户程序使用,它们工作在用户态。

运行处理器的和心态代码不受任何控制,可以自由地访问任何有效地址。而运行于用户态的代码则要受到处理器的诸多检查,它们只能访问映射表其地址空间的页表项规定的用户态可访问的页面的虚拟地址。

当一个任务执行系统调用而陷入内核代码执行时,我们就称为进程处于内核运行态(内核态)。
当进程正在执行自己代码时,则称其处于用户运行态(用户态)。

当CPU处于内核态,可以随意进入用户态,而当CPU处于用户态时,用户从用户态切换到内核态只有在系统调用和中断两种情况下发生。

内核线程和用户线程

内核线程

特点:

  • 由内核负责调度,一个内核线程处于阻塞状态时不影响其他的内核线程,因为它是调度的基本的单位。
  • 这些线程可以在全系统内进行资源的竞争
  • 内核空间内为每一个内核支持的线程设置了一个线程控制块(TCB),内核根据该控制块,感知线程的存在,并进行控制,只是创建、调度的开销要比进程小。
  • 内核线程由内核控制,当线程进行切换到时候,由用户态转为内核态,切换完毕要从内核态转为用户态,即存在用户态和内核态之间的转换。

优点:

  • 在多处理器系统中,内核能够同时调度同一进程中多个内核线程并执行到多个处理器中,如果进程中的一个线程被阻塞,内核可以调度到同一个进程中的另一线程。

缺点:

  • 即使CPU在同一个进程的多个线程之间切换,也需要进入内核态,因此起速度和效率不如用户线程

用户线程

  • 用户线程在用户空间实现,内核并不知道用户线程,内核的调度对象和传统进程一样,还是进程(用户进程)本身。
  • 不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。
  • 内核资源的分配仍然按照进程(用户进程)进行分配,各个用户线程只能在进程内竞争资源
  • 用户线程的由用户态程序自己控制,不需要内核干涉,少了进出内核态的消耗,但不能很好的利用多核CPU
  • 每个用户线程并不具有自身的县城上下文,因此,就线程的同时执行而言,任意给定时刻每个进程只能由一个线程执行,而且只有一个处理器内核会被分配给该进程。

优点:

  • 线程切换无需进入内核,故切换开销小

缺点:

  • 系统调用的阻塞问题:对应用程序来讲,同一进程中只能有一个线程在运行,一个线程的阻塞将导致整个进程中所有线程的阻塞,由于这里的处理器时间片分配是以进程为基本单位,所以每个线程的执行时间相对减少

内核线程和用户线程的联系

一对一模型:

  • 每个用户线程被映射一个内核线程,用户线程在其生命期内都会被绑定到内核线程,一旦用户线程终止,两个线程都将离开系统。

弊端:

  • 内核线程的数量有限
  • 内核线程的调度开销比较大

混合线程模型:
多对一:

  • 多个用户线程被映射到一个内核线程
  • 多对一模型线程的切换速度要快很多(线程切换由用户代码来执行)

弊端:

  • 如果某一个用户线程阻塞,所有的线程都无法执行

多对多:

  • 对上述两种模型进行结合,即将多个用户线程映射到不止一个内核线程中去
  • 多对多模型对用户线程的数量没有什么限制,在多处理器系统上也会有一定的性能提升,不过提升的幅度比不上一对一模型。

本内容参考:
死锁的产生原因以及四个必要条件
计算机操作系统
内核线程与用户线程的一点小总结 《程序员的自我修养》·笔记


dack
98 声望18 粉丝

一直在路上


« 上一篇
Java基础
下一篇 »
算法-leetcode