进程和线程
进程
为了帮助大家理解什么是进程,以厨师做蛋糕为例。厨师做蛋糕,首先需要厨师(CPU),其次,需要食谱(程序)和原料(输入数据),而用原料做蛋糕的一些列动作的总和就是进程。某天厨师正在后厨做着蛋糕,突来听到儿子哭着跑进后厨,说自己被蜜蜂蛰了 ,厨师放下手中工具,并记录下当前做到哪一步了(保存上下文信息) ,然后拿出急救手册,按其中的说明为儿子进行处理(开始另外一个进程)
文件是对I/O设备的抽象 虚拟存储器是对文件和主存的抽象 指令集是对CPU的抽象 进程是对指令集和虚拟存储器的抽象
从上图看出,进程包括指令集和虚拟存储器,虚拟存储器包括用户栈、堆、程序数据和程序代码,用户栈从上往下生长,堆从下往上生长,程序数据和程序代码从可执行文件加载而来
CPU运行到地址为304的指令, 假设CPU时间片刚好用完,就需要进行进程切换,在进行进程切换之前,需要保护现场,即保存寄存器信息、PC、打开的文件, 代码段地址、数据地址、堆栈信息等,这些信息称为进程的上下文。当操作系统切换到进程时,首先将进程2的上下文信息加载到操作系统中,找到PC,然后接着执行就可以了。
进程的上下文信息是以某个数据结构保存在内存中的,而这种数据结构就是PCB(task_struct)。
struct task_struct{ pid_t pid://进程号 long state;//状态 cputime_t utime,stime;//cpu在用户态和 核心态下执行的时间 struct files_struct *files;//打开的文件 struct mm_struct *mm;//进程使用的内存 ... }
进程的状态包括新建态、就绪态、等待态、运行态、退出态。
进程被新建,然后进入到就绪状态,此时,进程并没有进入到运行状态,而是等待CPU调度,如果被CPU调度则进入到运行态,而当时间片用完时,进程从运行态返回到就绪态,而当等待I/O操作时,则由运行态进入阻塞态。需要注意的是:只有运行态的进程拥有CPU,而处于就绪态和等待态的进程只是处于内存,等待CPU调度,因此CPU调度是一个很关键的流程。
CPU调度就是到底哪个进程占有CPU,它可以分为非抢占式和抢占式。非抢占式是指调度程序一旦把CPU分配给某一进程后便让它一直运行下去,直到进程完成或发生某件事件而不能运行时,才将CPU分配给其他进程。它适合批处理系统,简单、系统开销小。抢占式是指当一个进程正在执行时,系统可以基于某种策略剥夺CPU给其他进程。剥夺的原则有优先权原则、端进程优先原则、时间片原则,它适用于交互式系统。
线程
进程之间是相互独立的,所以进程间数据共享只能通过内核实现,开销很麻烦,因此我们提出了线程这个概念。
线程之间的数据是共享的;一个进程可以只有一个线程,也可以有多个线程(一个进程至少有一个线程);当一个进程有多个线程时,每个线程都有一套独立的寄存器和堆栈信息,而代码、数据和文件是共享的。