Linux进程控制
一、实验目的
1、通过进程的创建、撤销和运行加深对进程概念和进程并发执行的理解,明确进程和程序之间的区别;
2、分析进程争用临界资源的现象,学习解决进程排斥的方法;
3、熟悉Linux系统的使用和相关命令的使用。
二、 实验内容
1、实验原理
(1)fork()函数:
① 父进程:返回子进程的pid值;
② 子进程:返回0或-1(出错);
(2)exec()系列函数:执行新的命令;
(3)wait()函数:等待子进程结束使用;
(4)exit()函数:结束终止进程使用;
2、运用的理论知识及算法
Ubuntu 虚拟机的使用、基本命令行指令的使用和编写运行C语言代码。
3、程序流程图
(1)任务一:进程的创建
(2)任务二:子进程执行新任务
4、步骤和方法
(1)任务一:进程的创建
① 使用vi或gedit新建一个fork_demo.c程序;
② 编写一个程序,在系统中有一个父进程和一个子进程活动,使用系统调用 fork()创建一个子进程,与此同时编写父进程和子进程部分的代码,使父进程在屏幕上显示字符“b”,而子进程在屏幕上显示字符“a”,最后编写父子进程的公共执行的部分,令其在屏幕上显示字符“c”;
③ 编写完成后在命令行窗口输入“gcc –o fork_demo fork_demo.c”对代码进行编译,生成名称为fork_demo的可执行文件;
④ 在命令行输入./fork_demo运行该程序,分析多次运行的结果为何不同;
(2)任务二:子进程执行新任务
① 使用vi或 gedit 新建一个exec_demo.c程序;
② 编写一段程序,使用系统调用fork()创建一个子进程。子进程通过系统调用execlp()函数转换命令执行,然后调用exit()函数结束。父进程则调用waitpid()等待子进程结束,然后正常结束;
③ 编写完成后在命令行窗口输入“gcc –o exec_demoexec_demo.c”对代码进行编译,生成名称为exec_demo的可执行文件;
④ 在命令行输入./exec_demo运行该程序并分析结果;
5、关键代码
(1)任务一:进程的创建
while((x = fork()) == -1);
if (x == 0) {sleep(rand() % 2);printf("a");
} else {sleep(rand() % 3);printf("b");
}
printf("c");
(2)任务二:子进程执行新任务
if (pid < 0) {fprintf(stderr, "Fork Failed");return 1;
} else if (pid == 0) {execlp("/bin/ls", "ls", NULL);
} else {wait(NULL);printf("Child Complete");
}
三、实验结果与分析
1、任务一:进程的创建
(1)运行结果
(2)分析
对于创建的父进程和子进程而言,二者在资源竞争中的休眠时间不同(父进程休眠时间为“sleep(rand() % 3)”,而子进程休眠时间为“sleep(rand() % 2)”),因此会导致两个进程执行顺序不一致,所以会产生几种不同的输出。
2、任务二:子进程执行新任务
(1)运行结果
(2)分析
系统首先调用fork()函数创建了一个子进程。对于父进程而言,其返回的值为子进程的pid值,因此调用了wait()函数阻塞自身,等待子进程结束;而对于创建的子进程,其返回值为0,通过调用了execlp()函数更换自己原有的执行代码,转去执行Linux命令/bin/ls,最后通过调用exit()函数结束子进程,同时唤醒被阻塞的父进程,显示子进程的标识符,最后正常退出结束。
四、小结与心得体会
通过对Linux进程控制实验的学习,接触到了一些比较实用的函数,如fork()函数、exec()系列函数、wait()函数、exit()函数等等,同时了解了Linux进程控制的基本原理和实现方法,进一步熟悉并掌握了Linux系统的使用及其相关命令的使用方法。