CSAPP Chap8 关于Fork函数的一些练习与分析
来源:互联网 发布:java volatile用法 编辑:程序博客网 时间:2024/06/10 03:58
今天做了第8章的作业,感觉自己对fork函数的一些地方理解的不够深入,又怕期末考到这方面的题,就想在这方面理解的深入点,这篇文章只针对书上的练习给出一些比较合理的解释。
首先做这部分的题目需要上机验证,这就涉及到代码怎么运行的问题,都知道要加头文件csapp.h和csapp.c
但是在windos下运行这些代码都是有问题的,我查了一些资料发现要在linux下用gcc编译,需要将这两个文件放入user/include中,这个地址是只读不可写的,所以要用ubuntu下的root下的复制文件指令sudo 文件名 地址,并在gcc编译时加-lpthread。
前言就说到这里,接下来是关于fork函数的练习与分析。
8.13
求解可能输出,代码如下
#include "csapp.h"int main(){ int x=3; if(Fork()!=0) { printf("x=%d\n",++x); } printf("x=%d\n",--x); exit(0);}
分析一下结果还是比较容易看的,这类题最好画图做,但是我有点懒就不把图传上来了。
fork函数生成一个子进程,对于父进程要执行printf(“x=%d\n”,++x);语句,然后对于子进程和父进程,都要执行printf(“x=%d\n”,–x);语句,所以这个问题的结果是
x=4 父
x=3 父
x=2 子
或者
x=4 父
x=3 子
x=2 父
往这上面传图好麻烦,比较简单的题就不传了,ubuntu下验证和这个结果一样。
后面我想了一下,上面这个解释是不对的
fork函数的性质是“父进程和子进程对x所做的任何改变都是独立的,不会反映在另一个进程的存储器中”,意思就是【x父】和【x子】是两个不同的变参,考虑下面的程序
#include "csapp.h"int main(){ int x=3; if(Fork()!=0) { printf("x=%d\n",++x); } else printf("x=%d\n",--x); //printf("x=%d\n",--x); exit(0);}
这个程序对于x父和x子做不同的修改,打印值应该为
x=4 父
x=2 子
所以对于第一个例子,有了更合理的解释:对于父进程中的x,先做++x,输出x=4,然后再做–x,输出x=3,而对于子进程中的x,输出的一定是–x,即x=2
类似的考虑方法可以考虑以下代码:
#include "csapp.h"int main(){ int x=3; if(Fork()!=0) { printf("x=%d\n",++x); } else printf("x=%d\n",--x); printf("x=%d\n",--x); exit(0);}
这次就很容易分析了,结果是4 3 2 1,此处不赘述了 。
8.14
求hello会输出多少行
#include "csapp.h"void doit(){ if(Fork()==0) { Fork(); printf("hello\n"); exit(0); }}int main(){ doit(); printf("hello\n"); exit(0);}
我觉得在doit函数中,子进程生成两个进程,并都打印hello,然后回到主函数中,这些所有的进程都打印,加起来应该是2+3=5条。
但是验证后只有3条,想一想原因是在doit中的if语句内,执行完毕后exit(0),子进程和他创建出的进程都永远截止了,那么在执行完doit函数回到主函数中的时候,就只剩下一个父进程了,所以答案是2+1=3条
为了验证可以使用如下代码
#include "csapp.h"void doit(){ if(Fork()==0) { Fork(); printf("hello\n"); //exit(0); }}int main(){ doit(); printf("hello\n"); exit(0);}
相比原来的就是在exit(0)上加了注释,所以这次打印5行。上面这个例子其实就是8.15题。
8.16
#include "csapp.h"int counter=1;int main(){ if(Fork()==0) { counter--; exit(0); } else { Wait(NULL); printf("counter=%d\n",++counter); } exit(0);}
这题比较简单,针对子进程,修改了他的全局变量counter子,然后将该进程结束,对于父进程,做++counter并输出,故结果应该为counter=2
这里要注意的是,全局变量也是父进程和子进程各自独有的,而非共有。
8.18
#include "csapp.h"void end(void){ printf("2");}int main(){ if(Fork==0) atexit(end); if(Fork==0) printf("0"); else printf("1"); exit(0);}
题目中说了这个atexit函数是一一个指向函数的指针为输入,并将其添加到初始为空的函数列表中,当exit函数调用时会调用这个列表中的函数
我感觉这个题是最难的,因为这题要考虑到第一次运行fork时,对于第一个子进程调用atexit函数,在下一次的fork函数中,这个子进程生成的两个子进程的堆栈中都存了所谓的函数列表,并在最后的exit调用时会调用它们,所以会输出两个2,而这题的结果只要满足1-2,0-2的结构就可以了。
2016.6.8
- CSAPP Chap8 关于Fork函数的一些练习与分析
- 关于fork()函数的分析
- CSAPP Note chap8
- 关于CSAPP的一些资料
- 关于fork()函数特性的一些探究
- 关于fork()函数的精辟分析
- 关于fork()函数的精辟分析
- 关于fork()函数的精辟分析
- 关于fork()函数的精辟分析
- 关于fork()函数的精辟分析
- 关于fork()函数的精辟分析
- csapp读书笔记-fork函数详解
- 关于linux的fork用法的思考---读CSAPP
- 关于CSAPP 6.18的习题分析
- 琐记7:关于fork()函数的一些小知识
- fork()函数的精辟分析
- fork()函数的精辟分析
- fork()函数的精辟分析
- 单行/多行文本溢出,显示省略号
- Blog Started
- Intel搞了个“实感”3D摄像头:这是啥?
- dubbo registry 基本流程
- hdu3442(BFS)
- CSAPP Chap8 关于Fork函数的一些练习与分析
- 通过Git将项目上传到GitHub
- Simplify Path
- Hibernate基本映射
- emWin实现BMP位图皮肤之Multipage篇
- poj2251——Dungeon Master(BFS)
- C# winform TreeView设置为选中状态(蓝底白字)
- mysql导入导出.sql
- ajax与PHP示例