操作系统线程和进程
并行和并发
并行:一个时刻里多个任务在执行
并发:一个时间段里多个任务在执行
什么是进程
进程:一个具有独立功能的程序在一个数据集合上的一次动态执行过程
进程的组成
- 程序的代码
- 程序处理的数据
- 程序计数器的值,指示下一条将运行的指令
- 一组通用的寄存器的当前值,堆,栈
- 一组系统资源(如打开的文件/网络资源/磁盘IO资源)
总之,进程包含了正在运行的一个程序的所有状态信息
进程与程序的联系
- 程序是产生线程的基础
- 程序每次运行构成不同的进程
- 进程是程序功能的体现
- 通过多次执行,一个程序可以对于多个进程,一个进程可以包括多个程序(调度程序)
进程和程序的区别
- 进程是动态的,程序是静态的;程序是有序代码的集合;进程是程序的执行,进程还有核心态/用户态
- 进程是暂时的,程序是永久的;进程是一个程序运行的状态过程;程序可以长久保持
- 进程和程序组成不同;进程包括了程序、数据、和进程控制块(即进程状态信息)
进程的特点
- 动态性:可动态创建、结束进程
- 并发性:进程可独立调度和占用处理机运行:并发并行
- 独立性:不同进程的工作不影响
- 制约性:因访问共享数据/资源或进程同步而产生制约
描述进程的数据结构:进程控制块(PCB)
操作系统为每一个进程都维护了一个PCB,用来保存与该进程有关的状态信息
- PCB是进程的唯一标记
- 进程的创建:为该进程生成一个PCB
- 进程的终止:回收它的PCB
- 进程的组织管理:通过对PCB的组织管理来实现
PCB含有的三大信息
- 进程标识信息:如本进程的标识,本进程的产生者标识(父进程标识),用户标识
- 处理机(CPU)状态信息保存区:保存进程的运行现场信息
· 用户可见的寄存器:用户程序可以使用的数据,地址寄存器
· 控制和状态寄存器:如程序计数器(PC),程序状态字(PSW)
· 栈指针:过程调用/系统调用/中断处理和返回时需要用到它 - 进程控制信息
· 调度和状态信息,用于操作系统调度进程并占用处理机使用
· 进程间的通信信息,为支持进程间的与通信相关的各种标识,信号,信件等,这些信息存在接收方的进程控制块中
· 存储管理信息,包含指向本进程映射存储空间的数据结构
· 进程所用资源,说明有进程打开,使用的系统资源,如打开的文件等
· 有关数据结构连接信息,进程可以连接到一个进程队列中,或连接到相关的其他进程的PCB
PCB的组织方式
链表:同一状态的进程其PID成一链表,多个状态对应多个不同链表(各状态的进程形成不同的链表:数据链表,阻塞链表)
索引表:同一状态的进程归入一个index表(由index指向PCB),多个状态对应不同的index表(各状态的进行形成不同的索引表:就绪索引表,阻塞索引表)
进程状态
- 进程生命周期管理
· 进程创建:引起进程创建的三个主要事件(系统初始化时、用户请求创建一个新进程、正在运行的进程执行了创建进程的系统调用)
· 进程运行:内核选择一个就绪的进程,让它占用处理机并执行
· 进程等待:在以下情况下,进程等待(就绪):请求并等待系统服务,无法马上完成;启动某种操作,无法马上完成;需要的数据还没有到。注:进程只能自己阻塞自己,因为只有进程本身才能知道何时需要等待某种事件的发生,当进程的时间片用完是进入就绪状态,而不是阻塞状态
· 进程唤醒 :唤醒进程的原因:被阻塞进行需要的资源可被满足;被阻塞的进程等待的事件到达;将该进程的PCB插入到就绪队列。注:进程只能被其他进程或操作系统唤醒
· 进程结束:进程结束的几种情况。正常退出(自愿的),错误退出(自愿的),致命错误(强制性的),被其他进程杀死(强制性的)
进程状态变化模型
进程的三种基本状态:
进程在生命结束前处于且仅处于三种基本状态之一不同系统设置的进程状态数目不同。
运行状态:当一个进程在处理机上运行时
就绪状态:一个进程获得了除处理机之外的一切资源,一旦得到处理机就可执行
等待状态(阻塞状态):一个进程等待某一事件而暂停运行时。如等待某资源、等待输入/输出完成
进程挂起
进程在挂起状态时,意味着进程没有占用内存空间,处于挂起状态的进程映射映射在磁盘上
- 阻塞挂起状态:进程在外存并等待某事件的出现
- 就绪挂起状态:进程在外存、但只要进入内存,即可运行
状态队列
- 由操作系统来维护一组队列,用来表示系统当中所有进程的当前状态
- 不同状态分别用不同的队列来表示(就绪队列、各种类型的阻塞队列,分优先级)
- 每个进程的PCB都根据它的状态加入到相应的队列当中,当一个进程状态发送改变时,它的PCB从一个状态队列中脱离出来,加入到另外一个队列
进程和线程对比
- 进程是对运行时程序的封装,是系统调度资源的分配的基本单位
- 线程是进程的子任务,cpu调度和分配的基本单位,实现进程内的并发
- 一个进程可以包含多个线程,线程依赖进程存在,并共享进程内存
什么是线程安全
如何保证线程安全
- 互斥量(锁),通过互斥机制防止多个线程同时访问公共资源
- 信号量(Semphare),控制同一时刻多个线程访问同一个资源的线程数
- 事件(信号):通过通知的方式保持多个线程同步
进程间通信方式
- 管道/匿名管道/有名管道(pipe)
- 信号(Singal):比如用户使用ctrl+c产生SIGINT程序停止信号
- 消息队列(Message)
- 共享内存
- 信号量
- 套接字(socket):最常用的方式,web应用都是这种方式
死锁发生的四个必要条件:
(1) 互斥条件(选项D):一个资源每次只能被一个进程使用。
(2) 请求与保持条件(选项C):一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件(选项B):进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件(选项A):若干进程之间形成一种头尾相接的循环等待资源关系。
只要发生死锁,上述四个条件一定满足,只要有一个条件不满足,就不会发生死锁
因此,要避免死锁,只要破坏上述四个条件之一,主要有以下方法:
静态分配资源:破坏条件(2)和(4)
按序分配资源:破坏条件(4)
剥夺是分配:破坏条件(3)
而互斥地使用资源是多进程能正确工作的前提,是必须保证满足的,不能破坏,否则就会出现问题如读写不一致