#import "template.typ": *


#show: project.with(
  title: "实验二 进程的创建与控制",
  authors: (
    "absolutex",
  )
)

#align(right)[]

+ *实验目的*
  + 加深对进程概念的理解,明确进程和程序的区别；
  + 进一步认识并发执行的实质；
  + 熟悉C语言程序在Linux系统中的编辑，编译，执行；
  + 理解Linux系统中进程控制的基本原理。

+	实验内容：
  + 使用vi编辑如下C程序，然后进行调试，编译，多次执行，分析和思考执行结果。
    + #include_code("src/2.1.c")
      fork 了一个子线程，父子线程打印不同的输出，并且不作任何顺序要求。
    + #include_code("src/2.2.c")
      先打印 `ONE`，然后再 fork 出一个子线程，父子线程同时执行打印 `TWO`，因此最终结果一定是 `ONE,TWO,TWO,`
    + #include_code("src/2.3.c")
      首先 fork 出一个子进程，此时有两个进程（本题中未区分父子进程），分别打印 `ONE` 后，每个进程再 fork 出一个子进程，（此时有四个进程）打印 `TWO`。因此合法的输出有很多，只需要保证开头是 `ONE`，并且第二个 `ONE` 的位置在下标 $<= 3$ 时都可以。
    + #include_code("src/2.4.c")
      同理子进程打印 `ac`，父进程打印 `bc`，因此合法的输出可以是 `c` 不在开头，并且如果两个连着的 `c` 不在 (1,2) 的位置即可。但是可能是因为未刷新输出缓冲区，导致没有出现其他的结果。
  + 请编写一段程序，该程序将使用系统调用`fork()`来创建一个子进程。当这个程序运行时，系统中将有一个父进程和一个子进程活动。请让每个进程在屏幕上显示一个字符：父进程显示字符`A`，子进程显示字符`B`。同时，程序需要输出两个进程的进程标识符。为了达到预期的效果，我们需要首先显示子进程的输出字符`B`，然后显示父进程的输出字符`A`。
    #include_code("src/2.5.c")
  + 请编写另一段程序，该程序将使用系统调用`fork()`来创建两个子进程。当这个程序运行时，系统中将有一个父进程和两个子进程活动。请让每个进程在屏幕上显示一个字符：父进程显示字符`A`，两个子进程分别显示字符`B`和字符`C`。请多次执行这个程序，并观察记录屏幕上的显示结果，然后分析原因。
    #include_code("src/2.6.c")
    在 `handle_fork` 里，对于父进程将什么也不做，而对于子进程将打印字符。由于打印三个字符是不同的进程，没有任何顺序要求，因此 `ABC` 的任意输出顺序皆合法。
  + 请修改第二个实验中编写的程序，将每个进程输出一个字符改为每个进程输出一个字符50000次。请观察程序执行时屏幕上出现的现象，并分析原因。
    #include_code("src/2.7.c")
    由于有 wait 的存在，父进程会等待子进程打印结束再打印，因此 `B` 和 `A` 的出现顺序是固定的。


另外，本报告用到了一个 python 小脚本来多次运行程序并统计结果的频次：
#include_code("collect.py")