使用fork创建进程.docx

上传人:李司机 文档编号:1590227 上传时间:2022-12-09 格式:DOCX 页数:16 大小:74.19KB
返回 下载 相关 举报
使用fork创建进程.docx_第1页
第1页 / 共16页
使用fork创建进程.docx_第2页
第2页 / 共16页
使用fork创建进程.docx_第3页
第3页 / 共16页
使用fork创建进程.docx_第4页
第4页 / 共16页
使用fork创建进程.docx_第5页
第5页 / 共16页
点击查看更多>>
资源描述

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

1、使用fork创建进程L实验目的(1)理解LinUX实现系统调用的机制;(2)理解并掌握fork系统调用创建新进程的过程和原理;(3)掌握Vi(vim)、GCC和GDB的使用。2 .实验内容(1)通过编程验证fork函数的实现机制,并理解写时拷贝COW的意义;(2)使用fork和exec函数创建新进程。3 .实验方法(实验步骤)实验二步骤:第一步:双击打开进入IinUX的终端,用Vi新建一个Del_Sleep.C的文件第二步:创建成功之后,输入“a”或o”或i”进行插入编辑写入模式第三步:开始写我们的代码第四步:代码编辑完成之后,按“Esc”间退出编辑模式第五步:输入“:wq”对我们刚才编辑的代

2、码进行保存退出第六步:输入“gccDel_Sleep.c-oDel_Sleep”命令运行代码的编译成可执行文件第七步:然后输入“./a.out”或者./Del_Sleep进行代码的运行,得到我们程序的运行结果实验三步骤:第一步:双击打开进入IinUX的终端,用Vi新建一个Three_Fork.c的文件第二步:创建成功之后,输入“a”或o”或i”进行插入编辑写入模式第三步:开始写我们的代码第四步:代码编辑完成之后,按“Esc”间退出编辑模式第五步:输入“:wq”对我们刚才编辑的代码进行保存退出第六步:输入“gccThree_Fork.c-oThree_Fork,命令运行代码的编译成可执行文件第七

3、步:然后输入“/a.out”或者”./Three_Fork进行代码的运行,这时候就可以得到我们程序的结果实验四步骤:第一步:双击打开进入IirIUX的终端,用Vi新建一个two_before.c的文件第二步:创建成功之后,输入“a”或o”或i”进行插入编辑写入模式第三步:开始写我们的代码第四步:代码编辑完成之后,按“Esc”间退出编辑模式第五步:输入“:wq”对我们刚才编辑的代码进行保存退出第六步:输入“gcctwobefore.c-Otwo_before”命令运行代码的编译成可执行文件第七步:然后输入“./two_beforeou.tst进行代码的运行,第八步:继续输入catou.tst这时

4、候就可以查看我们程序的结果4 .实验过程(源代码、配置清单必须带注释)注释:源码中出现的定义Pid为进程号,PPid为父进程号,getppid为获取父进程id,getpid为获取子进程id,SleeP为睡眠时钟,fork函数为一次调用,返回两个值,子进程返回0,父进程返回子进程id标记,出错返回-1,exec函数把程序(保存在磁盘某个目录中的可执行文件)读入内存并执行,Exec函数不创建进程,而是用一个新的程序替换当前进程的代码段、数据段和堆栈。execve(,7binlszz,arg,NULL)为使用exec函数执行一个新的程序(binls)char*arg3=,7binls,-,NULL)

5、为定义一个字符串数组,最后一个数组元素为null1使用GCC调试C程序(预处理、编译、汇编、链接)预处理:对xx.c中的预处理命令进行处理,生成一个中间文件XX.iOrootubuntu:Rou文件(F)编辑(E)查看(V)线端(T)帮助(H)rootubuntu:#cdRourootubuntu:/Rou#IsThreeFork.*ThreeFork.crootubuntu:*/Rou#gccThreeFork.c-oThreeFork.iroottaubuntu:-/Rou#IsThreeFork.*ThreeFork.cThreeFork.iroot(Qubuntu:-/Rou#编译:对

6、中间文件xxi进行编译,生成ASCn的汇编语言文件XX.Srootubuntu:Rou文件(F)Si(E)Sfi(V)a(T)帮助(H)IrOOtiIbUntu:#cdRourootubuntu:/Rou#ISThreeFork.*IThreeFork.cThree_Fork.irootubuntu:/Rou#gccThreeFork.c-oThreeFork.srootubuntu:/Rou#LSThreeFork.*I程序“LS”尚未安装。您可以便用以下命令安装:apt-getinstallSlrootubuntu:-/Rou#IsThreeFork.*IThreeFork.cThree_

7、Fork.iThree_Fork.srootubuntu:/Rou#汇编:把汇编文件XX.S转换成可重定位的目标文件XX.OCQrootubuntu:-ZRou文件(F)媚辑(E)查看(V)帮助(H)rootubuntu:-#cdRouroottaubuntu:-/Rou#IsThreeFork.*ThreeFork.cThree_Fork.iThree_Fork.sroot(aubuntu:-/Rou#gccThreeFork.c-oThreeFork.oroot(aubuntu:-/Rou#IsThreeFork.*ThreeFork.cThreeFork.iThree_Fork.oThr

8、ee_Fork.srootubuntu:-/Rou#链接:把若干个可重定位的目标文件以及共享的库文件汇集成一个可执行的目标文件.root(g)ubuntu:Rou文件(F)编辑(E)Sfi(V)终端(T)帮助(H)rootubuntu:#cdRourootubuntu:-/Rou#IsThreeFork.*ThreeFork.cThreeFork.iThreeFork.oThreeFork.sroot(3ubuntu:-/Rou#gccThreeFork.c-oThreeForkrootubuntu:-/Rou#./ThreeForkbeforeforkingThisischildproces

9、s.pid=6946,ppid=6945Thisischildprocess.pid=6947fppid=6946Thisischildprocess.pid=6948,ppid=6947使用GDB调试C程序(quit退出调试)OCQroot(gubuntu:-/Rou文件(F)编辑(E)查看(V)终端Cr)用助(H)rootubuntu:-#cdRourootubuntu:-/Rou#gcc-gThreeFork.c-oThreeForkrootQubuntu:/Rou#gdb-qThreeForkReadingsymbolsfromrootRouThreeFork.done.(gdb)2E

10、xec函数的使用题1:使用exec函数执行一个新的程序(binls)源码0rootubuntu:-/Rou文由F)Htt(E)S(V)HiS(T)帮助(川#include-#include-#include*inmain(intargctchar*argv)pidtpid;int-i=;,getpid(),getppid(););char*arg=,printf(pid=fork();if(pid)(printf()elseif(pid=)printf(if(execve(printf(exit();elsesleep();printf(dn,getpid();)return;)0Qrootu

11、buntu:*Rou文件(F)SItt(E)fifi(V)tta)帮助(H)rootubuntu:/Rou#gccforkexec.crootubuntu:/Rou#./a.outiBeforeforking.Thisischildprocess.pid=6653,ppid=6652total96-rwxrw-rw-1rootroot1129Oct1322:042.c叩-rw-r-r-1rootroot761Oct1322:144.ci-rw-r-r-1rootroot805Oct1322:2944.c-rw-r-r-1rootroot2109Oct1322:3355.c-rwxr-xr-x1

12、rootroot4845Oct1401:44DelSleep-rwr-r-1rootroot395Oct1323:31DelSleep.c-rwr-r-1rootroot447Sep2900:01ExecTree.c-rwxr-xr-x1rootroot4955Oct1323:39ForkThree-rw-r-r-1rootroot439Oct1323:38FOrklThree.c-rw-r-r-1rootroot416Sep2900:17ForkThreeDeisleep.c-rw-r-r-1rootroot924Oct1401:37ThreeFork.c-nxrv-n-1rootroot8

13、85Oct1418:15ThreeforkTree.c-rwxr-xr-x1rootroot524Oct1418:55a.out-rwxrw-rw-1rootroot579Oct1418:55fork_exec.c-rw-r-r-1rootroot149Oct1401:40ou.tst-rw-r-r-1rootroot379Octl20:41pstreetest.c-rw-r-r-1rootroot91Octl21:36tree.cfrc,_1-cc+IUAGCi14crr+-一-3Fork函数的使用题2:去掉sleep源码Orootubuntu:*Rou文件(F)ttWE)fifl(V)终翻

14、T)WSI(H)Itincludemain(ntargc,char*argv)(pidtpid;printf(pid=fork();if(pid)();printf()elseif(pid=);printf()else,getpid(),getppid();printf()return;),getpid();Grootubuntu:*Rou文件(F)煽Ifl(E)杳看(V)终造(T)帮助(H)rootubuntu:#cdRourootubuntu:/Rou#gccDelSleep.c-oDelSleeproot(aubuntu:/Rou#./DelSleepbeforeforkingThisi

15、sparentprocess.pid=6631root0ubuntu:/Rou#Thisischildprocess.pid=6632,ppid=1题3:fork的三次调用源码rootubuntu:-/Rou文件(F)a(E)fi(v)()常助(H)ficludesincludewincludeintmain(intargc,char*argv)pidtpid;printf(.);pid=fork();net,;-if(pid)(printf(ln);)elseif(pid=)(printf(:.r:Jn,getpid(),getppid();else(sleep();printf(dn,ge

16、tpid();Ipid=fork();if(pid)printf(n);)elseif(pid=)printf(cin,getpid(),getppid();)else(sleep();printf(pcrentprocess二Cn,getpid();)/threetimespid=fork();if(pid)(printf(1n);)elseif(pid=)printf(,getpid(),getppid();)elsesleep();printf(dn,getpid();return;运行结果O*Qrootubuntu:Rou文件(F)编辑(E)fi(V)ita(T)朗助(H)rootub

17、untu:#cdRourootubuntu:/Rou#gccThreeFork.croot(aubuntu:/Rou#./a.outbeforeforkingThisischildprocess.pid=6500,ppid=6499Thisischildprocess.pid=65l,ppid=650Thisischildprocess.pid=652,ppid=65lIThisisperentprocess.pid=6499Thisisperentprocess.pid=650Thisisperentprocess.pid=65lThisischildprocess.pid=653,ppid

18、=6499Thisischildprocess.pid=654,ppid=65Thisischildprocess.pid=655,ppid=653Thisisperentprocess.pid=6499Thisisperentprocess.pid=6500Thisisperentprocess.pid=653Thisischildprocess.pid=656,ppid=6499Thisisperentprocess.pid=6499root(3ubuntu:/Rou#进程树(父进程与子进程关系)源码Grootubuntu:-Rou文件(F)编殂(E)查看(V)线端(T)帮助(H)Tree

19、fork(ispstree)(intpid;pldfork();if(pld)(printf();)elseif(pid*)elsesleep();ppid=getpid().pstreepid;PStree_PidTOrk();if(pstreepid)printf();else(lf(pstree_pld=)chea(:sprintf(a.ppd);char*arg(.,a,;if(execve(.arg,)(printf();exit();printf()elsesleep();1)ain().i:Treefork();printf();Irt1,j;for(i=:i;1+(Treefo

20、rk();sleep();)return;COQrootubuntu:Rou文件(F)编辑(E)有看(V)终选(T)帮助(H)FOotiIbUntu:TCdRouIrootubuntu:-/Rou#gccThreefork_Tree.crootubuntu:-/Rou#./a.outa.out(7172)-a.out(7173)-pstree(7174)a.out(7173)-a.out(7175)-pstree(7176)a.out(7172)-a.out(7173)-a.out(7175)Ipstree(7176)-a.out(7177)Ipstree(7174)-pstree(7178)

21、a.out(7175)-a.out(7179)-pstree(718)a.out(7177)-a.out(7181)-pstree(7183)a.out(7173)-+-a.out(7175)-+-a.out(7179)I-pstree(718)-a.out(7182)I-pstree(7176),-pstree(7184)a.out(7172)-+-a.out(7173)-+-a.out(7175)-+-a.out(7179)II,-pstree(718)-a.out(7182)-pstree(7176)I-pstree(7184)-a.out(7177)-a.out(7181)I-stre

22、e(7183)-a.out(7185)I-pstree(7174)-pstree(7178)-pstree(7186)rootUbUntU:Rouf题4:Cat命令查看可执行文件源码文件(F)M(E)fi*(V)(T)ffi0(H)/include#include#includemtmain(intargc,char*argv()pidtpid;printf(1);pid=fork();if(pidou.tstrootubuntu:-/Rou#catou.tst(beforeforkingThisischildprocess.pid=6599,ppid=6598IbeforeforkingTh

23、isispartentprocess.pid=6598irootubuntu:/Rou#5.思考题题2:去掉父进程的Sleep,会出现什么结果?如果父进程先运行,子进程后运行,为什么?eGrootubuntu:*Rou文件(F)埃Sa(E)杳看(V)终造(T)帮助(H)rootubuntu:#cdRourootQubuntu:-/Rou#gccDel_Sleep.c-oDelSleeproot(aubuntu:/Rou#./DelSleepbeforeforkingThisisparentprocess.pid=6631root0ubuntu:/Rou#Thisischildprocess.p

24、id=6632,ppid=1答:去掉父进程的Sleep,会发现只有父进程彻底执行完之后才会执行子进程。使用SleeP是为了防止父进程先退出,从而产生异常。一般来说,fork之后是父进程先执行还是子进程先执行是不确定的,这取决于内核使用的调度算法。这是因为对于进程的创建而言,子进程的形成需要很多的时间来复制父进程的大部分资源,代码段,数据段,创建Pid等,所以在这个时间里父进程会开始执行的,导致我们总是会直观的看到父进程总是先执行。而且在负荷非常重的系统中,谁先得到调度执行是由操作系统在运行时决定的,而且每次运行的结果也不一样。题3:写一个main()函数,执行3个fork,fork,fork,

25、会产生几个子进程?根据进程完善代码,并画出进程树0Qrootubuntu:-/Rou文件F)编辑(E)Sfi(V)Jta(T)帮助(H)Toot(3ubuntu:#cdRourootubuntu:/Rou#gccThreeFork.Crootubuntu:/Rou#./a.outbeforeforkingThisischildprocess.pid=650,ppid=6499Thisischildprocess.pid=65llppid=650Thisischildprocess.pid=65021ppid=6501Thisisperentprocess.pid=6499Thisisperen

26、tprocess.pid=6500Thisisperentprocess.pid=65lThisischildprocess.pid=653,ppid=6499Thisischildprocess.pid=654,ppid=65Thisischildprocess.pid=655,ppid=6503Thisisperentprocess.pid=6499Thisisperentprocess.pid=650Thisisperentprocess.pid=6503Thisischildprocess.pid=656,ppid=6499Thisisperentprocess.pid=6499roo

27、t(3ubuntu:-/Rou#答:会产生8个进程进程树:题4:运行a./forkdemoou.tst”,用cat查看ou.tst运行结果,出现两个beforeforking,为什么?Orootubuntu:Rou文件(F)编辑(E)M(V)终端(T)帮助(H)rootubuntu:*#cdRou*root0ubutu:/Rou#gcctwobefore.c-otwobeforeroot(3ubuntu:/Rou#.twobeforeou.tstroot(aubuntu:-/Rou#catou.tstbeforeforkingThisischildprocess.pid=6599,ppid=6

28、598beforeforkingThisispartentprocess.pid=6598rootubuntu:/Rou#答:在LinUX下,这种情况主要和Printf的缓冲机制有关。运行Printf,字符串内容会被放到缓冲区里,当程序运行到fork时,缓冲区里面的内容就会被子进程复制过去,因此在子进程缓冲区里面也就有了相应的字符串,这时,父进程和子进程都会有该相应的字符串内容,所以最终我们会看到beforeforking被打印两次6.实验体会答:在实验过程中,一直在考虑调用运行fork时会产生什么情况的父进程和子进程,两者处于什么关系,而且在调用fork产生进程时,会发现每次运行调用fork产生的进程中父进程和子进程都不一样,并且fork函数的就是调用一次,返回两次,在父进程中调用一次,在父进程和子进程中各返回一次。在这次实验中,我理解了在IimIX环境下通过调用fork和exec产生进程的原理、父进程与子进程的关系、Printf的缓冲机制、以及SIeeP在程序中的作用。虽然在这次实验中由于需要对这些知识进行反复梳理与理解,推导及证论上而花了很多时间,但也让我彻底明白了fork,exec,Printf及SIeeP的工作机制,理解LinUX实现系统调用的机制、Vi(Vin1)、gcc和gdb的使用和写时拷贝COW的作用,同时并掌握fork系统调用创建新进程的过程和原理,收获很大。

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号