进程
进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行的过程。 进程 = 程序+数据——>动态执行
特点:
- 动态性:客动态地创建、结束进程
- 并发性:进程既可以被独立调度并占用处理机运行
- 独立性:不同的进程的工作不相互影响
- 制约性:因访问共享数据/资源或进程间同步而产生制约
进程与程序的联系:
- 进程是操作系统处于执行状态程序的抽象。程序 = 文件(静态的可执行文件);进程 = 执行中的程序 = 程序 + 执行状态
- 同一个程序的多次至干性过程对应为不同进程。如命令“ls”的多次执行对应多个进程
- 进程执行需要的资源。内存:保存代码和数据;CPU:执行指令 ###进程与程序的区别:
- 进程是动态的,程序是静态的。程序是有序代码的集合;进程是程序的执行,进程有内核态/用户态
- 进程是暂时的,程序是永久的。进程是一个状态变化的过程;程序可长久保存
- 进程与程序的组成不同。进程的组成包括程序、数据和进程控制块
进程控制块(PCB Process Control Block)
定义:操作系统管理控制进程运行所用的信息集合。
操作系统用PCB来描述进程的基本情况以及运行变化的过程。
PCB是进程存在的唯一标志,每个进程都在操作系统中有一个对应的PCB
使用:
进程创建时生成该进程的PCB
进程终止时回收它的PCB
通过对PCB的组织管理来实现对进程的组织管理
内容:
- 进程标识信息。PID:进程号,UID等 哪个程序在执行,执行了几次,用户标识
- 处理机现场保存,主要就是寄存器,保存进程的运行现场信息:堆栈指针:记录堆栈现场;指令指针:记录进程运行到哪
- 进程控制信息:
- 调度和状态信息:进程和处理机使用情况调度
- 进程间通信信息:进程间通信相关的各种标识
- 存储管理信息:指向进程映像存储空间数据结构
- 进程所用资源:进程使用的系统资源,如打开文件等
- 有关数据结构连接信息:通过与PCB相关的进程队列实现
进程状态
划分在不同操作系统中可能不同,但是大致可以分为:
- 系统初始化时,创建INIT进程,INIT再负责创建其他进程;用户请求创建一个NEW PROCESS;正在运行的进程执行了创建进程的系统调用。
- 进程就绪:进程获取了除处理机之外的资源,得到了处理机即可运行
- 进程运行:内核选择一个就绪的进程,让它占用处理机(cpu)并执行
- 进程阻塞(等待)的三种情况:请求并等待系统服务,无法马上完成;启动某种操作(和其他进程协调工作),无法马上完成;需要的数据没有到达。进程自己触发阻塞,因为只有自己才知道何时需要等待某事件
- 进程抢占:进程会被抢占情况:高优先级进程就绪;进程执行当前时间用完。
- 进程唤醒的情况:需要的资源可被满足;等待的事件到达。因为自身没有占用cpu执行,所以只能被OS或其他进程唤醒
- 进程结束的情形:自愿(正常退出,错误退出),强制性的(致命错误,被其他进程所杀)

三状态模型
(1)运行:当一个进程在处理机上运行时,则称该进程处于运行状态。处于此状态的进程的数目小于等于处理器的数目,对于单处理机系统,处于运行状态的进程只有一个。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。
(2)就绪:当一个进程获得了除处理机以外的一切所需资源,一旦得到处理机即可运行,则称此进程处于就绪状态。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列。
(3)阻塞:也称为等待或睡眠状态,一个进程正在等待某一事件发生(例如请求I/O而等待I/O完成等)而暂时停止运行,这时即使把处理机分配给进程也无法运行,故称该进程处于阻塞状态。
进程挂起
当内存中没有就绪进程时,为了减少CPU的空闲时间,可以采用交换技术将内存中暂时不能运行的某些进程挂起,释放其所占用的内存资源,以便重新接纳一个新进程或外存上已具备运行条件的进程进入内存的进程就绪队列。进程挂起(也称换出)是指在内存中的进程被暂时移出保存到外存中(如磁盘)的过程
引起进程挂起的原因大致有以下三种:
- 用户的请求。
- 父进程的请求。
- 操作系统的原因。操作系统引起的挂起可分为以下三种:
- 交换。当操作系统发现系统的内存资源已经不能满足运行进程的需要时,可以将当前不重要的进程挂起,以达到平衡系统负载的目的。
- 出现问题或故障时。当系统出现故障时,操作系统会暂时将系统中涉及该故障的进程挂起(换出),等故障恢复后,再将这些进程恢复到挂起前的状态(换入,由外存调入到内存)。
- 操作系统的需要。为监视系统的活动,操作系统可以挂起和激活(将外存中的进程调入到内存)一些记录系统资源使用状况的进程和用户进程活动的记账进程。
线程
线程含义
进程中的一条执行流程,进程可以视为一个资源管理的平台,其中的线程负责执行。
线程优点
一个进程可以同时存在多个线程、各个线程之间可以并发执行、线程共享进程的地址空间、文件等资源。
线程缺点
一个线程崩溃,会导致其所属进程的所有线程崩溃。
线程与进程区别
- 进程是资源分配单位 线程是CPU调度单位
- 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈
- 线程能减少并发执行的时间和空间开销:线程切换时间比进程短:不需要切换页表等等
线程实现
用户线程,内核线程和轻量级进程
用户线程
不由操作系统进行管理,由线程库进行管理(即操作系统并不知道有用户线程的存在,均在用户态下管理)。
存在以下缺点:
- 如果一个线程发起系统调用而阻塞,则整个进程都在等待。
- 当一个线程开始运行,除非主动交出CPU,否则其他线程无法运行。
- 时间片分配给进程,分到线程的会更少,执行变慢。
内核线程
线程控制块TCB位于内核,每一次切换都涉及用户态和内核态的切换。
轻量级进程
它是内核支持的用户线程,一个进程可有一个或多个轻量级进程,每个轻量级进程由一个单独的内核线程来支持。
进程切换(上下文切换)
在切换进程的时候,保存该进程恢复时需要用到的必要数据化,例如程序计数器、栈指针等等。并恢复要切换的进程的必要数据。
进程控制的系统调用命令
fork 创建子进程,将父进程的地址空间拷贝一份(这里要注意fork函数实际上并没有在物理上进行copy,而是使用copy on write,这样能够显著的减少开销)
exec 在同一个进程里用一个新程序代替调用exec的那个进程
exit 终止进程,退出。大部分资源会被回收,但是类似PCB无法自己回收。
wait 父进程等待子进程结束,子进程会向父进程发送一个值。
进程创建
Windows进程创建API:CreateProcess
Unix进程创建系统调用:fork/exec。fork()把一个进程复制成两个进程,父子进程有各自的PID;接下来的exec()用新程序来重写当前进程,PID不改变。
fork()的开销:
对子进程分配内存 复制父进程的内存和CPU寄存器到子进程里 开销昂贵 考虑到fork()操作中内存复制是没有作用的,子进程可能会关闭打开的文件和连接,因此考虑将其合并到一个调用中,于是出现了vfork()。
vfork():
创建进程时,不再创建一个同样的内存映像,而是当调用exec()时才开始复制,而要被覆盖或者关闭的资源不再进行复制 一些时候称为轻量级fork() 子进程应该几乎立刻调用exec()
进程加载
系统调用exec( )加载新程序取代当前运行进程
系统调用exec( )允许进程“加载”一个完全不同的程序,并从main开始执行
exec调用成功时,它是相同的进程,但是运行了不同的程序
exec调用成功时,代码段、堆栈和堆(heap)等完全重写了
进程等待与退出
四、进程等待与退出
####等待: wait()系统调用是被父进程用来等待子进程的结束,一个子进程通过exit()向父进程返回一个值,父进程通过wait()接受这个值并处理。
Wait使父进程睡眠,当子进程调用exit()时操作系统解锁父进程,将通过exit()传递得到的返回值作为wait调用的返回值(连同子进程的pid一起)。
为什么要让父进程等?而不是直接结束?
当进程执行完毕退出后,几乎所有资源都回收到OS中。但有个资源很难回收,就是PCB,PCB是代表进程存在的唯一标识,OS要依据PCB执行回收。这个功能由父进程完成。
僵尸状态:
就是调用了EXIT但还没有wait返回的时候。将死,还没死。无法正常工作,只是等待被父进程回收。
有僵尸子进程等待时,wait()立即返回其中一个值;无子进程存活时,wait()立刻返回
进程的有序终止exit()
-
进程结束执行时调用exit(),完成进程资源的回收
-
exit()系统调用的功能:将调用参数作为进程的“结果”;关闭所有打开的文件等占用资源;释放内存;释放大部分进程相关的内核数据结构;检查是否父进程是否存活着(如果父进程存活,它保留exit()结果的值直到父进程需要它,进入zombie/defunct状态。如果父进程先于子进程死掉了,它释放所有的数据结构,这个进程死亡。 );最后清理所有等待的僵尸进程。