操作系统实验报告
实验题目 进程的创建
学生姓名 卢冠辰
学 号 2022217511
专业班级 计科 22-5 班
指导教师 田卫东
完成日期 2024.11.11
合肥工业大学 计算机与信息学院
1 实验目的和任务要求
掌握创建子进程和加载执行新程序的方法,理解创建子进程和加载执行程序的不同。
� 调试跟踪 fork 和 execve 系统调用函数的执行过程。
2 实验原理
实验五关注于创建子进程和加载执行新程序的方法,通过调试跟踪 fork 和 execve 系统
调用函数的执行过程,理解进程创建和执行程序的区别。fork 用于创建子进程,execve 用
于在已有进程中加载并执行一个新程序。
3 实验内容
3.1 在 Linux 0.11 应用程序中调用 fork 函数创建子进程
调用 fork 函数创建子进程
在 Linux 0.11 应用程序中调用 fork 函数创建子进程,并分析程序运行的结果。步骤如
下:
1. 按 F5 启动调试。
2. 待 Linux 0.11 启动后,使用 vi 编辑器新建一个 main.c 文件,编写如下的代码。其
中的 getpid 函数是一个系统调用函数,返回当前进程的进程号。
#define __LIBRARY__
#include <stdio.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
int pid;
printf("PID:%d parent process start.\n", getpid());
pid = fork();
if( pid != 0 )
{
printf("PID:%d parent process continue.\n", getpid());
}
else
{
printf("PID:%d child process start.\n", getpid());
printf("PID:%d child process exit.\n", getpid());
return 0;
}
printf("PID:%d parent process exit.\n", getpid());
return 0;
}
3. 使用命令 gcc main.c -o app 生成可执行文件 app。
图 1 生成 app 可执行文件
4. 执行 chmod +x app 命令为 app 文件添加可执行权限。
5. 执行 sync 命令,将文件保存到硬盘。
6. 使用命令./app 运行可执行文件 app,分析运行结果。
图 2 app 运行结果
在父进程中可以调用 wait 函数阻塞父进程,直到子进程退出后才会从这个函数中返回,
从而让父进程继续运行。该函数的原型在 include/sys/wait.h 文件中定义如下:
pid_t wait( pid_t * wait_loc )
按照下面的步骤继续使用 vi 编辑器修改 main.c 文件:
1. 在 printf(“PID:%d parent process continue\n”, getpid());语句前面添加一
行语句: wait(NULL);
图 3 更改 main.c
2. 重新编译、运行应用程序 app,观察运行结果与之前有何不同。
图 4 新 app 运行结果
查看父进程与子进程的运行轨迹
1. 为了方便观察父进程和子进程的运行轨迹,需要在进程结束的位置添加一个断点。
请读者在 kernel/exit.c 文件的第 166 行添加一个断点即可,这里就是一个进程在结束运行
后,让调度程序选择其他进程继续运行的代码。
2. 按 F5 启动调试。在 Linux 操作系统启动完毕之前会多次命中刚刚添加的断点,每次
命中断点后都按 F5 继续运行即可,直到 Linux 启动完毕。
图 5 Linux 启动击中断点
3. 在 Linux 的终端输入命令./app 后,父进程和子进程在结束时都会命中此断点,所
以在第一次命中断点时,可以按 F5 继续运行,在第二次命中断点时,在 VSCode 的“View”
菜单中选择“Command Palette...”,会在 VSCode 的顶部中间位置显示命令面板,输入“Lab:
New Visualizer View”命令后,VSCode 会在其右侧弹出一个窗口让读者查看可视化视图。
在右侧可视化视图顶部的编辑框中输入命令“#sched”后按回车(需要等待较长时间完成刷
新),就可以查看进程的运行轨迹。注意观察父进程和子进程创建和结束的顺序,如果读者
在父进程中调用了 wait 函数等待子进程结束的话,还可以看到父进程首先创建子进程,然
后父进程进入阻塞状态等待子进程结束,在子进程结束后父进程才会被唤醒的过程。
图 6 子函数击中断点