在上一篇博文中,我大概的总结了一下进程控制的操作,但今天听了女神学姐的讲座,又发现了一个有趣的问题。
上代码:
int main(int argc, char *argv[])
{
int i;
for(i=0; i<2; i++)
{
fork();
printf("-");
}
return EXIT_SUCCESS;
}
答案是6个“-”吗?NO,其实是8个。
我们来看这句printf("-"),要知道,printf是存在缓冲区的问题的,关于缓冲,我就偷用汤圆同学博客里的一段话
来给大家解释吧。
“由于Linux的标准函数库中,有一种被称作“缓冲I/O”的操作,其特征就是对应每一个打开的文件,在内存中都
有一片缓冲区。每次读文件时,会连续的读出若干条记录,这样在下次读文件时就可以直接从内存的缓冲区读取;
同样,每次写文件的时候也仅仅是写入内存的缓冲区,等满足了一定的条件(如达到了一定数量或遇到特定字符等),
再将缓冲区中的内容一次性写入文件。这种技术大大增加了文件读写的速度,但也给编程代来了一点儿麻烦。比如有
一些数据,认为已经写入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内。”
而上面的代码,就是因为printf语句有缓存,它把“-”放在了缓存里,以后执行fork语句的时候,连带缓存都一起
被复制了,所以当第一次fork时,程序被分为父、子两个进程。先说父进程,之后执行printf语句,这时候已经有一个
“-”被存入缓存了,然后执行i++,i=1,继续执行第二次fork,又分为父、子两个进程,这父子两个进程也都继承了缓存
里的那个“-”,之后父子进程分别执行printf语句,也就是说,此时父子进程各自的缓存里已经都有两个“-”了,然后i++,
i=2,退出for循环,遇到return,读出缓存,各输出两个“-”,一共4个“-”,退出程序;同理,第一次fork后的子进程也执行
了一模一样的过程,所以,最后输出的“-”一共有8个。
为了便于大家更好的理解,我很无耻的将一位大神的做的图偷了出来,此图很清楚的画出了整个程序的执行流程。
当我们将上面的代码稍微修改一下,改为printf(“-\n”),即:
int main(int argc, char *argv[])
{
int i;
for(i=0; i<2; i++)
{
fork();
printf("-\n");
}
return EXIT_SUCCESS;
}
答案就会如愿以偿的变成6个“-”了。
这是因为当程序遇到\n, \t, 或者fflush,缓冲区满了, 文件描述符关闭,程序结束等,就会将数据刷出缓冲区,
所以,在printf语句后加了\n,就会立即输出,然后清空缓存,所以下一次fork后,缓存里是没有“-”的,于是结果就
变成输出6个“-”了。
文中引用的汤圆同学的博客:http://blog.sina.com.cn/s/blog_678d241901018gcf.html
文中被我偷图的大神博客:http://coolshell.cn/articles/7965.html/comment-page-1#comments