第一个程序(经典面试题)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
int i;
for(i=0; i<2; i++){
fork();
printf("-");
}
return 0;
}
问上述程序输出几个"-"
先将进程图画出来如下:
通过分析知道是6个"-",可是答案却是8个,这是怎么回事呢。
知识点:
- 输出函数printf,是先将要输出的内容输出至缓冲区,待缓冲区满或遇到回车,进程结束等情况时就刷新缓冲区,将缓冲区的内容打印在屏幕上。
- fork函数是一次调用,两次返回,在子进程中返回0,在父进程中返回子进程的进程号。
- 最关键的一点,fork产生子进程时,子进程会复制父进程的缓冲区以及下面的代码接着执行。
解答:
- 在进程图的标号1和2处,是关键地方,因为这两处执行了fork函数,并且执行此条代码之前有输出语句。
- 在1处fork后产生的子进程复制了父进程中的"-",所以这时1处产生的子进程输出语句执行后缓冲区中有2个"-",2处原理同1。这样输出时就多产生了2个,所以最后答案是8个"-"。
扩展1:
做下修改,若是将题目程序for循环中的终止条件 i<2改为i<3,最后答案是多少。
- 答案是24个"-"。同样若是正常分析应该是14个,即2+4+8,由上面分析,在执行i=1时i多输出了2个,在i=2时,加上原先进程总共产生8个,其中的4个在复制缓冲区时复制了父进程的2个,故多输出了8个,即总共多输出10个,答案为24个。
扩展2:
- 那怎样让原程序输出6个"-“呢,简单措施就是在输出语句中加”\n",还有方法就是手动刷新缓冲区,即使用fflush(stdout),手动刷新缓冲区,就不会多输出了。
第二个程序
#include <unistd.h>
#include <stdio.h>
int main()
{
fork();
fork() && fork() || fork();
fork();
sleep(100);
return 0;
}
问上述程序除了父进程,共产生了多少个进程。
知识点:
对于A&&B||C到底是怎么执行的。
- 关键在于A和B都为真时,C是不执行的,还有A为假,B是不执行的。本题在有了A&&B||C的执行过程之后,进程图就不难画出来了。
- 补充一个:fork函数是一次调用,两次返回,在子进程中返回0,在父进程中返回子进程的进程号。
进程图:
最后除去父进程,还有19个进程。
第三个程序
void fork7()
{
if (fork() == 0) {
printf("Terminating Child, PID = %d\n", getpid());
exit(0);
}
else {
printf("Running Parent, PID = %d\n", getpid());
while (1) ;
}
}
void fork8()
{
if (fork() == 0) {
printf("Running Child, PID = %d\n",
getpid());