相关: os 0916 week2

进程切换 (内核当中的

上下文切换,暂停当前运行进程,从运行态变成其他状态;调度另一个进程从就绪状态变成运行状态。 要求

  1. 切换前,保存进程上下文
  2. 切换后,恢复进程上下文
  3. 快速切换。频繁的操作。系统运行效率。汇编实现。 进程生命周期的信息
  • 寄存器
  • cpu状态
  • 内存地址空间(大部分不用保存)

进程控制块 PCB:内核的进程状态记录

  • 内核为每个进程维护了对应的进程控制块, 保存信息
  • 内核将相同状态的进程的PCB放置在同一队列, 如何组织
    • 就绪队列
    • I/O等待队列
      • 每个设备一个队列,磁带0/1;磁盘0
    • 僵尸队列

后面三个为用户提供的系统调用服务

进程 创建

fork() exec()

fork()

父子进程,pid不同。

  • 复制父进程的所有变量和内存
  • 复制父进程的所有CPU寄存器(有一个寄存器除外)
  • 返回值不同,子进程返回0,父进程返回子进程的pid.
  • 地址空间的复制。 代码 数据 堆栈 除了数据的childpid部分区别。

exec() 程序加载和执行

系统调用exec()加载可执行的新程序取代当前运行进程

把整个地址空间换掉。代码 数据堆栈。

fork的开销

对子进程分配内存,复制父进程的内存和cpu寄存器到子进程里,开销昂贵。 在大多数情况下,我们调用fork之后调用execm在fork()操作中内存复制是没有作用的,子进程可能关闭打开的文件和连接。为什么不能结合它们在一个调用中? vfork() 创建进程时,不再创建一个同样的内存映像,一些时候称为轻量级fork,子进程应该几乎立即调用exec,现在使用cow技术。

进程加载

  • 允许进程加载一个完全不同的程序,并从main开始执行。(即_start)
  • 允许进程加载时指定启动参数(argc,argv)
  • exec调用成功时
    • 它是相同的进程
    • 但是运行了不同的程序
  • 代码段、堆栈和数据等完全重写

进程等待与退出 父子 关系

父进程等待子进程

  • wait() 系统调用用于父进程等待子进程的结束
    • 子进程结束时通过exit()向父进程返回一个值
    • 父进程通过wait()接受并处理返回值
  • wait()系统调用的功能
    • 有子进程存活时,父进程进入等待状态,等待子进程的返回结果 当某子进程调用exit时,唤醒父进程,将exit返回值作为父进程中wait的返回值
    • 有僵尸子进程等待时,wait()立即返回其中的某一个值??
    • 无子进程存活时,wait()立刻返回

有序终止 exit()

  • 进程结束执行时调用exit(),完成进程资源回收
  • exit()系统调用的功能
    • 将调用参数作为进程的“结果”
    • 资源回收,关闭打开的文件,分配的内存,创建的内核相关数据结构
    • 检查父进程是否还存活
      • 若存活,保留结果的值直到父进程需要它,进入僵尸 zombie/defunct状态
      • 若没有,释放所有的数据结构,进程结束
    • 清理所有等待的僵尸进程
  • 进程终止时最终的垃圾收集