进程与线程
程序:静态的,存放在磁盘里的一系列指令
进程:动态的,程序的一次执行过程(一系列状态机)
pid:每次运行时递增的,在操作系统上可以看到这一点
PCB:进程存在的唯一标志 在内核源码中对应include/linux/sched.h中的task_struct结构体
linux内核源码
进程在内存中的地址空间
- 用户空间 数据段 程序段
- 内核空间 PCB放在这里
进程是系统进行资源分配和调度的独立单位
进程特征: - 动态性 状态机的迁移
- 并发性 多个进程并发运行
- 独立性 能独立运行,独立获得资源,独立接受调度的基本单位(引入线程后就不是调度的基本单位,但还是获得资源的基本单位)
- 异步性 各并发进程运行是异步的,操作系统要提供同步机制来确保各进程间顺序性
- 结构性 每个进程都有一个PCB
进程的状态
- 创建态(NEW/新建态) 进程正在被创建 这个阶段操作系统为进程分配资源、初始化PCB
- 就绪态(READY) 进程创建完成后,便进入就绪态,处于就绪态的进程以及具备运行条件 但没有空闲cpu运行
- 运行态(RUNNING) 进程正在CPU上运行 进程运行结束,或运行过程中遇到不可修复的错误 会到终止态 时间片用完,剥夺CPU使用权,转为就绪态
- 阻塞态(Waiting/Blocked/等待态) 进程运行过程中,请求等待某个事件的发生(如通过系统调用请求打印机)打印机资源被重新分配给这个进程 进程会重新回到就绪态
- 终止态(Terminated/结束态) 程序运行结束后,执行exit系统调用 进程会进入终止态 操作系统让这个进程下CPU,并回收内存空间等资源,还要回收进程的PCB,终止完成后,进程就消失
linux进程状态观测
进程的组织方式: - 链接方式
- 索引方式
进程控制
就是实现进程的状态转换 操作系统要干什么
使用原语实现 原语
原语使用关中断和开中断这两个特权指令实现,实现了原语的原子性
- 创建原语
- 撤销原语
- 阻塞原语
- 唤醒原语
- 切换原语
切换原语会把CPU寄存器状态放到pcb里,在时间片到要运行的时候从里面恢复状态
原语在linux内核中实现
进程通信
两个或多个进程之间产生数据交互
为什么进程通信需要操作系统支持?
出于安全考虑,进程之间的地址空间不能随意相互访问,需要操作系统的支持
通信方式:
-
共享存储 shm_open(...)申请共享区 mmap()把共享内存映射到进程地址空间
-
消息传递
- 直接通信 使用receive send原语 在内核中有一个消息队列
- 间接传递(信箱)通过信箱间接传递数据
-
管道通信: 与共享存储相比自由度降低,不能随意存取,有先进先出的特性
-
信号(25考纲新增)
线程
为什么要引入线程:一个进程也要同时做很多事如聊天视频传文件
带来的变化
- 线程变成了调度的基本单位,进程还是资源分配的基本单位
- 提高了并发度
- 不需要切换进程环境,减少了系统开销
用户级线程: - 运行在用户态,不需要操作系统管理,开销小
- 进程还是CPU调度的基本单位
内核级线程: - 运行在内核态,比用户级线程开销大
- 线程是CPU调度的基本单位
组合方式: - 一对一模型 一个用户级线程对应一个内核级线程
- 多对一模型 多个用户级线程对应一个内核级线程
- 多对多模型 n个用户级线程对应m个内核级线程==(n>m)==
所有的内核级线程都被阻塞时,才称进程进入了阻塞态