进程与线程(上)
1. 进程
- 运⾏中的程序,就被称为「进程」
- 进程的状态
挂起状态:描述进程没有占⽤实际的物理内存空间的情况
阻塞挂起状态:进程在外存(硬盘)并等待某个事件的出现
就绪挂起状态:进程在外存(硬盘),但只要进⼊内存,即刻⽴刻运⾏
- 通常会把阻塞状态的进程的物理内存空间换出到硬盘,等需要再次运⾏的时候,再从硬盘换⼊到物理内存
2. 进程的控制结构(PCB)
- 进程描述信息 (进程唯一标识符、用户标识符)
- 进程控制和管理信息
记录进程状态,如 new、 ready、 running、 waiting 或 blocked 等
进程优先级:进程抢占 CPU 时的优先级
- 资源分配清单
- CPU 相关信息
- 每个PCB通过链表组织
将所有处于就绪状态的进程链在⼀起,称为就绪队列
把所有因等待某事件⽽处于等待状态的进程链在⼀起就组成各种阻塞队列
3. 进程的上下文切换
- 各个进程之间是共享 CPU 资源的,⼀个进程切换到另⼀个进程运⾏,称为进程的上下⽂切换
- 进程上下文切换的内容:
包含了虚拟内存、栈、全局变量等⽤户空间的资源,还包括了内核堆栈、寄存器等内核空间的资源。通常,会把交换的信息保存在进程的 PCB
- CPU上下文
CPU 寄存器和程序计数是 CPU 在运⾏任何任务前,所必须依赖的环境,这些环境就叫做 CPU上下⽂。也就是记录指令位置
CPU 上下⽂切换就是先把前⼀个任务的 CPU 上下⽂(CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下⽂到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运⾏新任务
4. 线程
- 线程是进程当中的⼀条执⾏流程
同⼀个进程内多个线程之间可以共享代码段、数据段、打开的⽂件等资源,但每个线程各⾃都有⼀套独⽴的寄存器和栈,这样可以确保线程的控制流是相对独⽴的
5. 线程优点
- ⼀个进程中可以同时存在多个线程
- 各个线程之间可以并发执⾏
- 各个线程之间可以共享地址空间和⽂件等资源
6. 线程缺点
- 当进程中的⼀个线程崩溃时,会导致其所属进程的所有线程崩溃
7. 线程上下文切换
- 两个线程不是属于同⼀个进程
切换的过程就跟进程上下⽂切换⼀样
- 两个线程是属于同⼀个进程
因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器、栈等不共享的数据
8. 线程实现
- 用户线程
- 内核线程
- 轻量级进程
9. 用户线程
- 在用户空间实现的线程,不经过内核管理
基于动态的线程管理库实现
⽤户线程的整个线程管理和调度,操作系统是不直接参与的
多个⽤户线程对应同⼀个内核线程
- 优点:
每个进程都需要有它私有的线程控制块(TCB)列表 ,可用于不支持线程的操作系统
⽆需⽤户态与内核态的切换,所以切换速度特别快
- 缺点:
由于操作系统不参与线程的调度,⼀个线程发起了系统调⽤⽽阻塞,那进程所包含的⽤户线程都不能执⾏了
一个线程使用CPU就必须等到,线程主动释放,进程中其他线程无法运行:因此代码创建的线程肯定不是用户线程
由于时间⽚分配给进程,故与其他进程⽐,在多线程执⾏时,每个线程得到的时间⽚较少,执⾏会⽐较慢
10. 内核线程
- 内核空间创建的线程(java创建的线程)
- 优点
一个线程阻塞、不会影响其他内核线程的运⾏
资源直接分配给线程,多线程的进程获得更多的 CPU 运⾏时间
- 缺点
内核维护进程和线程的上下⽂信息,如 PCB 和 TCB,维护任务大
线程的创建、终⽌和切换都是通过系统调⽤,系统开销⽐较⼤
11. 轻量级进程
- 轻量级进程(Light-weight process,LWP)是内核⽀持的⽤户线程,⼀个进程可有⼀个或多个 LWP,每个 LWP 是跟内核线程⼀对⼀映射的,也就是 LWP 都是由⼀个内核线程⽀持。就是Linux线程的统称
12. 线程和进程比较
- 进程是资源(包括内存、打开的⽂件等)分配的单位,线程是 CPU 调度的单位
- 进程拥有⼀个完整的资源平台,⽽线程只独享必不可少的资源,如寄存器和栈
- 线程同样具有就绪、阻塞、执⾏三种基本状态,同样具有状态之间的转换关系
- 线程能减少并发执⾏的时间和空间开销
线程的创建时间⽐进程快:进程创建需要额外的资源管理信息
线程的终⽌时间⽐进程快,因为线程释放的资源相⽐进程少很多
同⼀个进程内的线程切换⽐进程切换快:因为线程具有相同的地址空间(虚拟内存共享)拥有同一个页表
数据交互效率更高:由于资源共享,数据传递不需要经过内核
13. 调度
- 先来先服务调度算法
- 最短作业优先调度算法
- ⾼响应⽐优先调度算法
- 时间⽚轮转调度算法
- 最⾼优先级调度算法
- 多级反馈队列调度算法(时间轮片+最高优先级)
多级:有多个队列,队列之间时间轮片
反馈,一个队列有优先级更高进程加入,则立刻执行优先级更高的
14. 进程间通信
- 每个进程的⽤户地址空间都是独⽴的,不能互相访问,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核
15. 管道
- Linux 命令中「 | 」这个竖线。,就是管道
功能是将前⼀个命令( ps auxf )的输出,作为后⼀个命令( grep mysql )的输⼊
从这功能描述,可以看出管道传输数据是单向的
「 | 」表示的管道称为匿名管道,⽤完了就销毁
- 命名管道,也被叫做 FIFO ,数据先进先出
通过 mkfifo 命令来创建,并且指定管道名字
管道这种通信⽅式效率低,不适合进程间频繁地交换数据
- 管道背后原理
通过int pipe(int fd[2]) 这个系统调用创建,返回fd[0]读取端描述符和fd[1]写入端描述符
匿名管道是特殊的⽂件,只存在于内存
所谓的管道,就是内核⾥⾯的⼀串缓存
管道只在父子进程(fork出子)间通信:通常父进程通知子进程
shell ⾥⾯执⾏ A | B 命令的时候 :A和B之间不存在父子关系。她俩的父进程都是shell
- 匿名管道,它的通信范围是存在⽗⼦关系的进程
- 命名管道,它可以在不相关的进程间也能相互通信
涵盖各大厂考官最爱问知识点,22年最新整理!