Lab 4:内核线程管理

进程

进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程。

进程控制块(PCB,Process Control Block)是操作系统管理控制进程运行所用的信息集合。

进程控制块主要包含以下 3 类信息:

  • 进程的标识信息:如执行的程序、进程 ID、父进程等
  • 进程的状态信息:如状态寄存器、内存地址空间、进程状态等
  • 进程所占用的资源信息:如堆栈、存储等

进程的基本状态:

  • 等待态:等待外设
  • 就绪态:等待CPU
  • 运行态:占有CPU

线程

线程是进程的一部分,描述指令流执行状态。它是进程中的指令执行流的最小单元,是 CPU 调度的基本单位。

线程的优点:

  • 一个进程中可以同时存在多个线程
  • 各个线程之间可以并发地执行
  • 各个线程之间可以共享地址空间和文件等资源

线程的缺点:

  • 一个线程崩溃,会导致其所属进程的所有线程崩溃

线程 = 进程 - 共享资源。线程与进程的比较:

  • 进程是资源分配单位,线程是 CPU 调度单位。
  • 进程拥有一个完整的资源平台,而线程只独享指令流执行的必要资源,如寄存器和栈
  • 线程同样具有就绪、等待和运行三种基本状态和状态间的转换关系
  • 线程能减少并发执行的时间和空间开销
    • 线程的创建时间比进程短
    • 线程的终止时间比进程短
    • 同一进程内的线程切换时间比进程短
    • 由于同一进程的各线程间共享内存和文件资源,可不通过内核进行直接通信。
  • 进程主要是隔离,线程主要是共享。

实现线程通常有三种方法:

  • 用户线程:在用户空间实现
  • 内核线程:在内核中实现
  • 轻量级进程:在内核中实现,支持用户线程

进程控制

Unix 进程创建系统调用:fork/exec:

  • fork() 把一个进程复制成二个进程,parent(old PID)child(new PID)
  • exec() 用新程序来重写当前进程,PID 没有改变

用 fork 和 exec 创建进程的示例:

int pid = fork();  // 创建子进程
if(pid == 0){  // 子进程在这里继续
    // Do anything
    exec("program", argc, argv0, argv1, ...)
}

子进程的 fork() 返回 0,父进程的 fork() 返回子进程标识符,fork() 返回值可方便后续使用,子进程可使用 getpid() 获取 PID。

fork 的实现大致为:

  1. 父进程复制 PCB
  2. 修改 PCB 中的进程 ID
  3. 将复制修改好的 PCB 放入就绪队列

exec 的实现大致为:

  1. 读取磁盘中的程序
  2. 将其加载到相应地内存地址

实验

创建进程相关的数据结构和算法。

具体而言,创建进程控制块(PCB)数据结构,创建进程创建(do_fork)函数。

打印字符串