欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

当fork遇见for循环,printf后会怎样?

程序员文章站 2022-06-03 13:14:03
...

这段时间总看见这种题,今天总结一下。

题1

先看代码1:

#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int main()
{
    printf("1 2 3");
    fork();
}

代码2:

#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int main()
{
    printf("1 2 3\n");
    fork();
}

以上两段代码基本一样,不一样的就是‘\n’,我们自然能想到缓冲区的问题。
printf
这条命令处理起来却应该分为两步:

  1. 系统将printf()中传进的数据写进进程的缓冲区
  2. 对于标准输出而言(行缓冲),系统判断如果缓冲区中有“\n”,或是EOF,或是主动刷出,或是缓冲区满,或是文件描述符关闭,或是exit,就会把数据从缓冲区中输出出来(flush)

也就是说对于printf()代表的行缓冲而言,数据只是先被存储在了缓冲区,直到碰见上述情况才会输出。如果缓冲区内有内容,当进程退出时(exit)也会自动进行输出。
我们再来看这两段代码,我们先看一下结果:
代码1:
当fork遇见for循环,printf后会怎样?
代码2:
当fork遇见for循环,printf后会怎样?
结果分析
代码1中主进程的缓冲区因为执行时没有输出条件,所以内容被子进程继承,两个进程结束时触发exit,输出缓冲区内容,结果为
1 2 3 1 2 3
而代码2因为执行时有’\n’条件所以主进程输出1 2 3后缓冲区刷空,子进程继承来空的buffer自然无输出,结果为
1 2 3

题2

基于题一的知识,我们看题2。
代码1:

#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int main()
{
    int i=0;
    for(i=0;i<2;i++)           
    {
        fork();
        printf("-");
    }
    return 0;
}

代码2:

#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int main()
{
    int i=0;
    for(i=0;i<2;i++)           
    {
        fork();
        printf("-\n");
    }
    return 0;
}

结果:
代码1:
当fork遇见for循环,printf后会怎样?
代码2:
当fork遇见for循环,printf后会怎样?
基于题一的解释,应该各输出几个-呢?
题中,有两层循环:
(1)一次循环后有两个进程,
代码1中主进程的缓冲区因为执行时没有输出条件,所以内容被子进程继承,此时两个进程的缓冲区各有一个’-’ 。
代码2中因为有执行条件’\n’,所以主进程和子进程各打印出一个’-’
(2)第二次循环后,两个进程分别fork出各自的子进程,所以共四个进程,
代码1中,同理,fork出的子进程继承父进程的缓冲区,此时四个进程的缓冲区都有’-‘,再次执行printf,各自的缓冲区都多了一个’-‘,结束时触发exit,输出缓冲区内容,结果为8个。
而代码2中,四个进程缓冲区为空,执行printf,打印四个,共6个。

题三

看代码,共有多少个进程数?

#include<stdio.h>
int main()
{
  fork();
  fork()&&fork()||fork();
  fork();
}

我们需要知道几个问题:

  1. 父进程fork出子进程,子进程从fork后面那个指令开始执行的
  2. fork后父进程返回子进程PID,子进程返回0
  3. 对于”a&&b”表达式,如果a为0,b就不会执行

(1)第一次fork,进程A变成A和其子进程B
当fork遇见for循环,printf后会怎样?
(2)fork()&&fork()||fork();

分析如下图:
当fork遇见for循环,printf后会怎样?
注意:
C和D都是子进程,那么它俩返回的值都是0,因此”&&”后面的表达式就不会执行,之后执行最后一个fork()函数。

但是A和B两个父进程返回值大于0,因此会执行后面的”fork()||fork()”

(3)最后一次fork
当fork遇见for循环,printf后会怎样?

所以带最开始的A进程,共20个进程。

相关标签: fork for printf