fork()函数的面试题

fork()函数的面试题

今天我们分析一下fork()常出现的一些面(笔)试题,以备以后面试或者笔试被提及到,我们知道fork()这个函数是一种特殊的函数,它有两个返回值,一个是子进程的pid,一个是父进程的pid,那么它们的这些特别之处,到底会给它们带来什么样的变化呢,我们接下来开始分析。

fork()函数的标准模式:pid_t pid = fork();

代码一:

面试题一: 

   int i =0;
    for (; i<2; i++)
    {
        fork();
        printf("a\n");
    }

看以上代码,我们接着看图进行分析:


当 i= 0 的时候,fork()执行一次,创建出来了一个子进程,又由fork()函数的特殊性我们知道,当fork()执行的时候,它产生的子进程也会从fork()执行以下的代码继续开始执行,从而创建的子进程也会打印一个a,而父进程本身也会打印一个a,就是上图的 i = 0 的过程;

而当 i= 1 的时候,进行第二次的循环,而这时候,里面存在了两个进程,即i= 0时候代码本身的进程,还有i= 0 的时候创建的新进程,都参与这次的循环,则当第二次fork()的时候以上两个进程都会被作为父进程来参与创建新的进程,则当i= 1 的时候,由原来存在的两个进程fork()成为了四个进程,所以这次要打印四个a,加上i= 0的时候两个a,一共打印了6个a。

Linux平台下结果如下:



代码二:验证:

(1)
printf("a");
fork();

(2)
printf("a\n");
fork();
从上面代码我们可以看出,它们唯一的区别是在printf函数中(1)比(2)少了一个'\n',那么它们这小小的区别会不会影响到它们的运行结果呢,接着我们看看一下两个运行结果:

(1)的结果:


(2)的结果:


从上面我们可以看出,(1)没有'\n'打印两个a,而(2)有'\n'打印了一个a;我们知道fork()这个函数是产生一个子进程,而子进程的数据是和父进程的数据是一样的,那么为什么第一个打印2个a,第二个打印1个a呢。首先,这样分析,printf这个函数它每次把数据打印到我们所看到的屏幕上时,它会先将数据放在缓存区里,而我们这里的'\n'作用就是把缓冲区刷新,所以在我们(1)中,没有'\n'会使得缓冲区没有刷新,导致子进程也会把printf这个函数中的数据给带过去,使得在子进程中也打印一个a,所以这里产生两个a;而在(2)中,有'\n'使的printf打印完,缓冲区立即刷新,而当fork()执行的时候printf这个函数中,也就是缓冲区中已经没有a了 ,相当于被清空了,所以只能打印一个a。这里我间接的在说明缓冲区的刷新这个知识点,那么使得缓冲区刷新的条件还有哪些呢?

缓冲区什么时候刷新条件:
1、 遇到“\n” ,立即刷新缓冲区
2、 程序调用 fflush 这个函数立即刷新缓冲区
3、 程序以 exit 结束, 缓冲区会刷新。 如果以_exit 结束, 缓冲区数据被直接
清空。
4、 缓冲区满, 也会将缓冲区数据刷新出来。 1024 字节


代码三:

面试题二:

 int i =0;
    for (; i<2; i++)
    {
        fork();
        printf("a");
    }

从以上代码我们可以看出,它与我们的本文所述的面试题一的唯一区别也就是少了一个'\n',而我们在代码题2中已经说过了,有'\n'缓冲区会立即刷新,那么我们看一下这个fork()以后的结果是怎么样的,是不是与”面试题一”中的结果一样,也是6个a,还是其他呢,先看图:


由图中所看出,一开始i= 0的时候,fork()函数创建一个新的进程,然后我们不妨把第一次循环的打印为a1,这样,第一次打印两个a1,而当第二次fork()的时候,没有'\n'缓冲区没有刷新,使得进程在复制的时候,把a1也从他们相应的父进程复制了过来,这时候他们自身打印一个a,还有一个在父进程中复制过来的a1,第二次的时候父进程也参与printf打印,所以就是4个a1和4个a,也就是8个a。
Linux平台下结果如下:



代码四:面试题三:

  fork() || fork();
    printf("a\n");

此代码是fork() || fork()那么结果是如何呢,先看图,结合分析:


第一个fork()的时候,fork为真的时候,直接打印a,第二个fork()不参与判断;当第一个参数为假的时候,第二个参数开始进行判断,则第二个fork()有两种情况真和假,所以一共三种情况,所以a要打印三次。

Linux平台下结果如下:



扩充:

由于以下题的类型与上述一样,不做说明。

 扩展题一:与‘面试题’一类型一样

int main()
{
int i = 0;
for(; i < 2; ++i)
{
if(fork())
{
printf(“A\n”);
} 
else
{
printf(“B\n”);
}
}
}
结果:   AAA BBB


扩展题二:与‘代码三’题型一样

int main()
{
int i = 0;
for(; i < 2; ++i)
{
if(fork())
{
printf(“A”);
}
else
{
printf(“B”);
}
}
}
结果:AA BA AB BB


扩展题三:与‘代码四’题型一样

int main()
{
if(fork() || fork())
{
printf(“A\n”);
} 
else
{
printf(“B\n”);
}
}
结果: AAB


  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值