1、进程的概述
1.1 从程序到进程
二进制可执行文件:在Linux文件格式为ELF,交给操作系统执行后就变为进程了
一个程序可对应多个进程,一个进程可包含多个程序
Linux可执行文件的组成:
- 文件头
- 代码
- 初始化数据
- 未初始化数据
进程地址空间:
- 共享库:存放共享库函数
- 栈:存放函数的参数、返回值、局部变量
- 堆:为用户程序中的malloc分配内存
- 初始化数据
- 代码
1.2 什么是进程
进程:可以并发执行的程序在某个数据集合上的运行过程,是系统进行资源分配和调度的独立单位
- 程序
- 数据
- 进程控制块(PCB)
1.3 进程特征
- 结构性:程序 + 数据 + PCB
- 动态性:创建、执行、调度、消亡
- 并发性:内存中有多个进程同时执行
- 独立性:资源分配和调度的独立单位
- 异步性:各自独立运行,不知道谁先结束
1.4 进程状态
- 就绪态
- 运行态
- 阻塞态:上一个状态一定是运行态,在运行中被阻塞
2、进程控制块
2.1 进程控制块(PCB)
进程控制块(PCB):数据结构,描述进程的当前的运行情况,以及控制进程运行的全部信息
- 进程标识信息:唯一的标识进程,比如PID
- 处理器现场信息:
- 通用寄存器:8~32个,RISC结构中超过100个
- 指令计数器:下一条指令的地址
- 状态寄存器:程序状态字PSW
- 用户栈指针:过程和系统调用参数及地址
- 进程调度信息:
- 进程状态
- 进程优先级
- 该进程在等待的事件
- 调度所需其他信息
- 进程控制信息:
- 程序和数据的地址
- 进程间同步和通信机制:需要的消息队列指针和信号量等
- 资源清单及使用情况
- 家族关系:父子进程关系及其它结构
2.2 Linux中的task_struct结构
Linux中PCB用task_struct结构体表示
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
struct thread_info thread_info;
#endif
volatile long state;
pid_t pid;
pid_t tgid;
volatile:gcc编译器修饰符,告诉编译器不要优化,从内存读取它的值而不是从寄存器
pid:进程标识符
tgid:线程组ID
struct task_struct __rcu *real_parent;
struct task_struct __rcu *parent;
struct list_head children;
struct list_head sibling;
struct list_head *group_leader;
2.3 Linux如何存放PCB
thread_info存放进程PCB中频繁访问和需要快速访问的字段,第一个字段是task_struct结构
3、进程控制机制
3.1 CPU执行状态
用户态:执行非特权指令;访问通用寄存器和分配资源
系统态(核心态):访问所有资源;执行特权/非特权指令
CPU状态通过PSW(程序状态字)进行标识,X86的PSW有2位二进制:00系统态,11用户态
- 用户态 -> 内核态:
- 系统调用(软中断/访管指令);
- 设备中断;
- 异常
- 内核态 -> 用户态:直接设置程序状态字PSW
3.2 原语
在操作系统中,原语可以用于控制共享资源的访问
原语:由若干条机器指令执行的并用以完成特定功能的一段程序,这段程序在执行期间不允许中断,又称为“原子操作”过程,作为一个整体而不可分割
3.3 进程创建
- 操作系统初始化,建立起一些常驻内存的系统进程
- 使用创建原语,用于创建非常驻内存系统进程和用户进程
- 创建一个空白PCB,分配一个唯一的进程标识符;
- 为新进程的程序和数据分配内存空间;
- 初始化进程控制块:初始化标识符信息,填入处理机的状态信息(指令指针,栈指针)和控制信息(状态,优先级…);
- 设置相应的链接,如把新进程加到就绪队列的链表中
3.4 进程状态转换
进程阻塞:正在运行的进程等待待某一事件发生(如请求系统服务、等待键盘输入等),主动调用阻塞原语(block)将自己阻塞,让出CPU给其他进程
- 保存CPU现场到PCB中
- 状态由运行态改为阻塞态
- 插入到时间阻塞队列中
- 进程调度程序选中一个就绪进程,修改状态,恢复CPU现场,投入运行
进程唤醒:当被阻塞进程期待的时间到来时,由中断处理进程或其它产生该事件的进程调用唤醒原语(wakeup),将期待该事件的阻塞进程唤醒
- 触发事件:硬件中断;其他进程发消息
- 阻塞进程从阻塞队列移除
- 状态由阻塞态改为就绪态
- 插入到就绪队列中
进程挂起:进程将自己挂起或父进程将子进程挂起时,调用挂起原语(suspend)挂起
- 活动就绪态 -> 静止就绪态
- 活动阻塞态 -> 静止阻塞态
- 运行态 -> 静止就绪,并触发重新调度
进程激活:调用激活原语(active)将指定进程激活
- 静止阻塞态 -> 活动阻塞态;
- 静止就绪态 -> 活动就绪态;
若采取抢占调度策略,被激活进程优先级高则触发重新调度
3.5 进程中止
一旦发生中止进程的事件,OS便调用撤销原语
- 若进程处于执行态,应立即中止该进程的执行,并置调度标志为真
- 若有子孙进程则将其全部中止,以防它们失控
- 将该进程所占用的全部资源还给父进程或系统
- 将该进程的PCB从所在队列中移出,回收PCB