计算机系统之深入理解fork()函数(面试题) | 您所在的位置:网站首页 › fork函数的规则 › 计算机系统之深入理解fork()函数(面试题) |
最近在深入理解计算机系统(CSAPP)这门课上学到了异常控制流(Exception Control Flow)这一章节,其中书上关于fork()有许多理解。 我们今天就先来做一道面试题目理解理解fork()函数具体的含义。 1.第一题题目描述
根据下面的手绘图,我们可以看到总共有6个printf,于是我们不难猜到答案是6个Hello。
我们可以发现系统输出了8个Hello。 原因是 在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,变量值,环境变量,缓冲区,等等。 而printf语句其实并不会马上把结果输出到屏幕上,而是先到缓存区里面,在进行缓存区输出到屏幕。 \n 其实不仅仅代表着换行的意思,还包括清空缓存区。我们在调用fork()时,缓存区也被复制到子进程。 所以在最后,由原本的父进程输出2次,子进程输出2次。变成了父进程输出4次,子进程输出8次。 最后我们还可以验证一下我们的结论,一般fflush(stdout)是用来刷新缓存,我们把它加进程序,重新编译看看效果。
做这题我们要知道fork函数有两个返回值,fork()的作用是产生一个子进程。 如果调用成功则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1。 上图就是因为父进程快于子进程运行,所以先输出Linux,再输出Hello。 所以我们的改动是加上一个wait()函数。 wait函数的作用是会暂停当前进程,直到子进程结束。 进程一旦调用了wait,就会马上阻塞自己,由wait()自动分析当前进程的某个子进程是否已经退出,如果它找到了这样一个已经变成僵尸进程的子进程,wait()收集此子进程信息后销毁且返回。 所以,在fork()之后加上wait()进行判断,此时主进程由fork()返回子进程ID(非0)并被wait()强制暂停;子进程由fork()创造并返回0,打印Hello随后被销毁。 我们就可以直接看代码和结果了。系统输出的是HelloLinux。 请问总共创建了多少个进程? 这个题目要解出来主要看第4行代码。 第3行和第5行都是只有一个fork(),所以会产生4个分支,剩下的就是看如何解析第4行了。 当 A && B,如果A = 0,则不继续执行 && B。如果A≠0,则继续执行 && B。 当 A || B,如果 A ≠ 0,则不继续执行 , 如果A = 0,则继续执行 || B。 假设当我们仅执行第4行代码时,手绘图如下: 前面算出2个fork()是4个分支,所以4×5 = 20,总共有20个分支,去掉main主线程。 我们就可以得到答案是创建了19个线程。 |
CopyRight 2018-2019 实验室设备网 版权所有 |