实验名称:进程管理

  • 实验学时:2学时

预习报告 2021-04-28

实验原理摘要

  • 系统调用是一种进入系统空间的办法,在OS的核心中都设置了一组用于实现各种系统功能的子程序,并将它们提供给程序员调用。程序员在需要OS提供某种服务的时候,便可以调用一条系统调用命令,去实现希望的功能,这就是系统调用。
  • 在linux系统中,进程控制的功能是由内核的进程控制子系统实现的,并以系统调用的形式提供给用户进程或其他系统进程使用。

实验仪器

  • PC机
  • Linux (CentOS7)

实验内容及步骤

  • 实验内容
    • 编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每个进程在屏幕上显示一个字符,父显示" parenter ",子进程分别显示“son”和“daughter”,观察记录显示结果,并分析原因
  • 实验步骤
    • 使用touch命令创建一个p.c文件
    • 使用vi编辑p.c
    • 编译文件 gcc p.c -o p
    • 执行文件 ./p
    • 反复执行源文件,观察记录显示结果,并分析原因

实验报告 2021-04-29

实验目的及要求:

  • 加深对进程概念的理解,明确进程和程序的区别与联系
  • 进一步理解并发的概念,明确并发与顺序执行的异同
  • 熟悉进程的创建、执行、阻塞、唤醒、终止等控制方法

实验环境

  • PC机
  • VMware Workstation Pro 15.x
  • Linux (CentOS 7)

实验内容

  • 编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每个进程在屏幕上显示一个字符,父显示" parenter ",子进程分别显示“son ”和“daughter ”,观察记录显示结果,并分析原因。

实验步骤

  • 打开终端在输入命令 touch p.c
  • 在终端输入命令使用vi编辑 vi p.c
  • 输入以下程序代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include<stdio.h>
    #include<unistd.h>
    int main(void){
    int p1, p2;
    while((p1 = fork()) == -1);
    if(p1 == 0){
    printf("Son ");
    }else{
    while((p2 = fork()) == -1);
    if(p2 == 0){
    printf("Daughter ");
    }else{
    printf("Parenter ");
    }
    }
    printf("\n");
    return 0;
    }
  • 编译源文件 gcc p.c -o p
  • 反复执行 ./p

实验结果

  • 执行结果

  • 观察反复执行后的输出结果, 我们可以发现程序运行结果有的是: “Parenter Son Daughter”, 有的是"Parenter Daughter Son", 结果有多种可能性。

  • 自己本身的C语言程序是没有问题的,但是为什么会有多种输出结果?

    • 对于父进程来说,除了创建两个子进程之外,还要输出"Parenter",于是父进程和子进程需要竞争CPU用来输出字符串"Parenter",但是CPU当前调用什么进程,就会执行什么进程。输出结果为"Parenter Son Daughter"的意思是:先运行父进程,并输出,然后子进程被创建,成为就绪队列,父进程可以运行,继续创建第二个子进程。就程序的并发性来看,是有多种输出结果的,父进程和子进程没有同步措施,因此父进程与子进程的输出内容会叠加在一起,所以父进程和子进程的输出结果是随机的。
    • 对于子进程来说,因为在有三个进程时,不同的操作系统的调度算法不一样,因此也有其他的输出顺序。
    • 对于Printf()函数来说,他在输出字符串的过程中不会被中断,因此,字符串内部字符顺序输出不变。但是由于进程并发运行的调度顺序和父子进程抢占CPU的问题,输出字符串的顺序和先后随着执行的不同而发生变化。

总结

  • 通过这次上机实验,我们了解并掌握了如何在Linux操作系统下编辑、编译和运行C语言文件。
  • 对于它的执行过程和整体的结构有一定的了解