1. 进程切换
又称 上下文切换
- 暂停当前运行进程,从运行状态变成其他状态
- 调度另一个进程从就绪变成运行
要求:
- 切换前,保存进程上下文
- 切换后,恢复进程上下文
- 快速切换
由汇编实现,因为需要速度快
PCB里记录:内核的进程状态
内核将相同状态的进程的PCB放置在同一队列。
2. 进程创建
Windows进程创建API:CreateProcess(filename)
Linux进程创建API:fork/exec(execute)
调用fork()后的状态变化(exec调用新进程)
fork()使用示例
创建成功后,放入就绪队列中。
创建一个内核线程
fork()的实际开销
子进程复制父进程的内存和CPU寄存器到子进程里,开销巨大
因为99%情况下,在调用fork()后会调用exec()
所以在fork()中的内存复制是不必要的
这时候!
我们使用vfork()
采用Copy on Write(COW技术,也叫 写时复用 技术
3. 进程加载
允许进程“加载”一个完全不同的程序,并从main开始执行(即_start)
允许进程加载时指定启动参数(argc, argv)
代码段,堆,栈等完全会被重写。
ucore中exec()实现
- sys_exec 获取参数
- do_execve 加载,核心
- load_icode 识别可执行文件,核心
4. 进程的等待与退出
父子进程进行资源的回收
wait()系统调用用于父进程等待子进程的结束
- 子进程结束时通过exit()向父进程返回一个值
- 父进程通过wait()接受并处理返回值
功能:
- 如果有子进程存活,父进程进入等待状态
- 子进程调用exit(),父进程唤醒,将exit()返回值作为父进程wait()的返回值
- 有僵尸子进程等待时,父进程wait()立刻返回其中一个值
- 无子进程存活,wait()直接返回
进程的有序终止exit()
- 调用exit(),完成进程资源回收
功能:
- 将调用参数作为进程的结果
- 关闭所有打开的文件等占用资源
- 释放内存
- 释放大部分进程相关的内核数据结构
- 检查父进程是否存活
- 存活:保留结果值直到父进程需要它,进入僵尸状态(zombie/defunct)状态
- 没有存辉:释放所有数据结构,进程结果
子进程在exit()检查父进程
父进程在wait()检查子进程
进程控制 和 进程状态 关系