赞
踩
实验一:熟悉Linux命令及进程管理
目前流行的Linux系统很多,我选择利用virtual box中安装虚拟ubuntu系统完成本次实验。如下图:在virtual box中新建ubuntu环境后,设置好ubuntu虚拟镜像环境就可以使用了。
为了使操作不受限,在ubuntu中设置超级用户:
2、linux操作系统基本命令
|
|
|
Vi的基本操作:
|
3、在linux系统中编写并运行C程序
在ubuntu中主要有两种方式来运行C语言程序:
值得注意的是,将windows操作系统中的代码直接共享到ubuntu系统中,也有两种方式:
代码段1的运行结果分析:我采用方法一(利用文本编辑器保存c代码), 程序1、
代码分析:
1)在父进程中,fork返回新创建子进程的进程ID,这时i是大于0的,因此会进入if语句中执行wait操作,并等待子进程执行完毕; 2)在子进程中,fork返回0,因此会执行else中的操作; 3)如果出现错误,fork返回一个负值;
wait函数功能是:父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。 当父进程忘了用wait()函数等待已终止的子进程时,子进程就会进入一种无父进程的状态,此时子进程就是僵尸进程. wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID. 执行步骤与结果如下图所示:
|
根据上图所示的分析结果,容易发现:
为了验证上述的猜想,把wait函数改写成wait(NULL),得到以下输出结果:
分析以上结果,发现父进程的fork和wait函数的返回值都是子进程的pid=4074,父进程的pid为4073,说明此时wait函数是正常返回的。 程序1运行的进程数如下图所示:
|
程序2的代码及运行结果分析:
printf(“b.My process ID is %d”,getpid());
printf(“c.My process ID is %d”,getpid());
|
执行结果:
从代码的第5行开始分析,首先执行fork,fork执行完后,系统中出现两个进程,分别是p1和p0。 根据if条件语句,可以判断出p1为子进程,执行if语句,输出语句b;p0为父进程继续执行else语句;进入else循环后,原父进程p0继续执行fork语句,此时根据if条件判断,系统又产生了新的子进程p2,输出语句c, 最后原父进程p0输出语句a。 多次执行程序2,发现输出结果并不相同: 如上图所示,有时先创建的进程的执行速度反而慢于后创建的进程的执行速度。这是因为当fork语句执行成功后创建新进程后,这些进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。
|
程序3的代码和结果分析;
|
根据运行结果,系统共执行了三次fork,共生成了8个进程。
|
程序4的运行结果:
|
多次运行程序4的结果并不相同,根据上图所示,可以发现最后执行完的进程可能是父进程也可能是子进程,有时先创建的进程的执行速度反而慢于后创建的进程的执行速度。这是因为当fork语句执行成功后创建新进程后,这些进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。 |
编写程序实现进程树 |
|
程序的运行结果如下:
结果分析,在最初的程序设计时,创建了6个进程,后来我发现,这是因为父进程的p1共享给了它第二次创建的子进程,所以第二次创建的子进程也会进入if(p1>0)的条件语句中,修改条件语句,则成功实现程序所要求的进程树。
|
程序的进程树如上图所示。 |
在本次实验中,我安装并学习了linux系统的基础操作,并通过分析linux进程创建的核心代码,fork和wait函数,理解了Linux系统创建子进程的过程,fork函数是一个神奇的函数,通过该系统函数的调用,它调用一次可以产生两个返回值,并为当前进程产生一个新的子进程,这里有一点特别值得注意,在fork语句之前,该进程的所有资源,包括代码、变量都会等价的复制给子进程,如果忽略了这一点,很容易在编写程序自己创建进程树的时候出错。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。