使用fork创建进程.docx

上传人:b****5 文档编号:6881200 上传时间:2023-01-12 格式:DOCX 页数:11 大小:961.41KB
下载 相关 举报
使用fork创建进程.docx_第1页
第1页 / 共11页
使用fork创建进程.docx_第2页
第2页 / 共11页
使用fork创建进程.docx_第3页
第3页 / 共11页
使用fork创建进程.docx_第4页
第4页 / 共11页
使用fork创建进程.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

使用fork创建进程.docx

《使用fork创建进程.docx》由会员分享,可在线阅读,更多相关《使用fork创建进程.docx(11页珍藏版)》请在冰豆网上搜索。

使用fork创建进程.docx

使用fork创建进程

使用fork创建进程

1.实验目的

(1)理解Linux实现系统调用的机制;

(2)理解并掌握fork系统调用创建新进程的过程和原理;

(3)掌握vi(vim)、GCC和GDB的使用。

2.实验内容

(1)通过编程验证fork函数的实现机制,并理解写时拷贝COW的意义;

(2)使用fork和exec函数创建新进程。

3.实验方法(实验步骤)

实验二步骤:

第一步:

双击打开进入linux的终端,用vi新建一个Del_Sleep.c的文件

第二步:

创建成功之后,输入“a”或“o”或“i”进行插入编辑写入模式

第三步:

开始写我们的代码

第四步:

代码编辑完成之后,按“Esc”间退出编辑模式

第五步:

输入“:

wq”对我们刚才编辑的代码进行保存退出

第六步:

输入“gccDel_Sleep.c-oDel_Sleep”命令运行代码的编译成可执行文件

第七步:

然后输入“./a.out”或者“./Del_Sleep”进行代码的运行,得到我们程序的运行结果

实验三步骤:

第一步:

双击打开进入linux的终端,用vi新建一个Three_Fork.c的文件

第二步:

创建成功之后,输入“a”或“o”或“i”进行插入编辑写入模式

第三步:

开始写我们的代码

第四步:

代码编辑完成之后,按“Esc”间退出编辑模式

第五步:

输入“:

wq”对我们刚才编辑的代码进行保存退出

第六步:

输入“gccThree_Fork.c-oThree_Fork”命令运行代码的编译成可执行文件

第七步:

然后输入“./a.out”或者“./Three_Fork”进行代码的运行,这时候就可以得到我们程序的结果

实验四步骤:

第一步:

双击打开进入linux的终端,用vi新建一个two_before.c的文件

第二步:

创建成功之后,输入“a”或“o”或“i”进行插入编辑写入模式

第三步:

开始写我们的代码

第四步:

代码编辑完成之后,按“Esc”间退出编辑模式

第五步:

输入“:

wq”对我们刚才编辑的代码进行保存退出

第六步:

输入“gcctwo_before.c-otwo_before”命令运行代码的编译成可执行文件

第七步:

然后输入“./two_before>ou.tst”进行代码的运行,

第八步:

继续输入“catou.tst”这时候就可以查看我们程序的结果

4.实验过程(源代码、配置清单必须带注释)

注释:

源码中出现的定义pid为进程号,ppid为父进程号,getppid为获取父进程id,getpid为获取子进程id,sleep为睡眠时钟,fork函数为一次调用,返回两个值,子进程返回0,父进程返回子进程id标记,出错返回-1,exec函数把程序(保存在磁盘某个目录中的可执行文件)读入内存并执行,Exec函数不创建进程,而是用一个新的程序替换当前进程的代码段、数据段和堆栈。

execve("/bin/ls",arg,NULL)为使用exec函数执行一个新的程序(/bin/ls)

char*arg[3]={"/bin/ls","-l",NULL}为定义一个字符串数组,最后一个数组元素为null

1使用GCC调试C程序(预处理、编译、汇编、链接)

预处理:

对xx.c中的预处理命令进行处理,生成一个中间文件xx.i

编译:

对中间文件xx.i进行编译,生成ASCII的汇编语言文件xx.s

汇编:

把汇编文件xx.s转换成可重定位的目标文件xx.o

链接:

把若干个可重定位的目标文件以及共享的库文件汇集成一个可执行的目标文件

 

④使用GDB调试C程序(quit退出调试)

 

2Exec函数的使用

题1:

使用exec函数执行一个新的程序(/bin/ls)

源码

运行结果

 

3Fork函数的使用

题2:

去掉sleep

源码

运行结果

题3:

fork的三次调用

源码

运行结果

进程树(父进程与子进程关系)

源码

运行结果

题4:

cat命令查看可执行文件

源码

运行结果

5.思考题

题2:

去掉父进程的sleep,会出现什么结果?

如果父进程先运行,子进程后运行,为什么?

答:

去掉父进程的sleep,会发现只有父进程彻底执行完之后才会执行子进程。

使用sleep是为了防止父进程先退出,从而产生异常。

一般来说,fork之后是父进程先执行还是子进程先执行是不确定的,这取决于内核使用的调度算法。

这是因为对于进程的创建而言,子进程的形成需要很多的时间来复制父进程的大部分资源,代码段,数据段,创建pid等,所以在这个时间里父进程会开始执行的,导致我们总是会直观的看到父进程总是先执行。

而且在负荷非常重的系统中,谁先得到调度执行是由操作系统在运行时决定的,而且每次运行的结果也不一样。

题3:

写一个main()函数,执行3个fork,fork,fork,会产生几个子进程?

根据进程完善代码,并画出进程树

答:

会产生8个进程

进程树:

题4:

运行“./forkdemo>ou.tst”,用cat查看”ou.tst”运行结果,出现两个beforeforking,为什么?

答:

在Linux下,这种情况主要和printf的缓冲机制有关。

运行printf,字符串内容会被放到缓冲区里,当程序运行到fork时,缓冲区里面的内容就会被子进程复制过去,因此在子进程缓冲区里面也就有了相应的字符串,这时,父进程和子进程都会有该相应的字符串内容,所以最终我们会看到beforeforking被打印两次

6.实验体会

答:

在实验过程中,一直在考虑调用运行fork时会产生什么情况的父进程和子进程,两者处于什么关系,而且在调用fork产生进程时,会发现每次运行调用fork产生的进程中父进程和子进程都不一样,并且fork函数的就是"调用一次,返回两次",在父进程中调用一次,在父进程和子进程中各返回一次。

在这次实验中,我理解了在linux环境下通过调用fork和exec产生进程的原理、父进程与子进程的关系、printf的缓冲机制、以及sleep在程序中的作用。

虽然在这次实验中由于需要对这些知识进行反复梳理与理解,推导及证论上而花了很多时间,但也让我彻底明白了fork,exec,printf及sleep的工作机制,理解Linux实现系统调用的机制、vi(vim)、gcc和gdb的使用和写时拷贝cow的作用,同时并掌握fork系统调用创建新进程的过程和原理,收获很大。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1