fork()函数有关实验及解析

fork()是什么?

fork()的原理其实非常简单:当你调用fork()时,会产生一个子进程,这个子进程会拥有父进程所有的东西(记住,是所有)更通俗一点来讲,在函数代码段中,调用fork后,调用一次,返回两次,如果返回0,则代表当前的进程是子进程,不是的话则是父进程。接下来我们看段代码深入理解一下:

int main(int argc, char *argv[]) 
{
   
    pid_t pid;
    int x = 1;

    pid = Fork(); //line:ecf:forkreturn
    if (pid == 0) {
     /* Child */
	printf("child : x=%d\n", ++x); 
	fflush(stdout);
	return 0;
    }

    /* Parent */
    printf("parent: x=%d\n", --x); 
    fflush(stdout);
    return 0;
}

代码中先定义了x=1,之后调用了fork并获取返回值,它判断了pid的值,如果等于0,代表是子进程,则输出child:x= ,如果是父进程则输出parent:x= ,在这里要注意两个进程是相互独立互不干扰的,所以每一次的输出结果可能都会不一样,我本次输出的是:

  • child:x=2
  • parent: x=0

如答案所示:判断pid等于0,则是子进程输出x加一之后的值,之后则退出,return 0直接为退出程序,而到了父进程的时候,x仍为1,则父进程输出x减一之后的值。怎么样,看到现在是不是有点明白原理了呢?接下来一大波实验即将来袭!

实验一

void fork1() 
{
   
    if (fork() == 0) {
   
	printf("Hello from child\n");
    }
    else {
   
	printf("Hello from parent\n");
    }
}
int main(){
   
	fork1();
}

这个是很简单的例子,如果是子进程则输出Hello from child,父进程则输出Hello from parent。
则输出结果可能是以下可能:

  1. Hello from child
    Hello from parent
  2. Hello from parent
    Hello from child

还有一点不知道有没有细心的小伙伴注意到,上面实验中有一个fflush(stdout),而这个实验中没有,而是换行符。
首先呢,对于一个shell中运行的程序,默认的标准输出是控制台,而控制台是行缓冲的,也就是系统在缓冲区看到换行符,就帮你冲洗缓冲区。如果调用fflush,也可以触发输出,这就是强制冲洗。因此,如果只写输出语句不加换行,屏幕上是不会有语句的哦~不仅不会,有的时候还会产生令你满头问号的结果,因此,养成一个良好的习惯,从现在做起!

实验二


void fork2()
{
   
    int x = 1;
    pid_t pid = fork();

    if (pid == 0) {
   
	printf("Child has x = %d\n", ++x);
    } 
    else {
   
	printf("Parent has x = %d\n", --x);
    }
    printf("Bye from process %d with x = %d\n", getpid(), x);
}
int main(){
   
	fork2();
}

fork2
可以看到运行结果,调用fork后,子进程拥有父进程所有代码,所以printf也要执行,即如上图所示,也可以观察到子进程和父进程的进程号。

实验三

void fork3()
{
   
    printf("L0\n");
    fork();
    printf("L1\n");
    fork();
    printf("Bye\n");
}
int main(){
   
	fork3();
}

在这里插入图片描述
好的,我估计到这里就有人开始头冒问号了,这里我用最通俗的语言讲一下,不然再看下去的小伙伴就会秃头了!
大家可以在本子上画一个进程图,就会很清晰
我们可以从图中看出大体结构,打印完L0只后,调用了fork返回两个进程父进程继续往下走,打印L1,调用fork又返回两个进程,父进程继续往下走,打印bye,而第一个fork的子进程只会继承fork之后的代码,因此打印L1后继续调用fork,再产生两个子进程,只后如上,但因为所有的父进程和子进程都是相互独立的(就是当前干嘛完全是计算机想干啥干啥,反复横跳,但要记住,要有bye必须得先有L1,要想有L1,必须得先有L0)所以输出可能性就有很多种,有啥可能性呢?如下(这里就不换行了 麻烦):

  1. L0 L1 Bye L1 Bye Bye Bye
  2. L0 L1 L1 Bye Bye Bye Bye
  3. L0 L1 Bye Bye L1 Bye Bye

好了,你有没有列出来呢,接下来难度升级哦,准备好!

实验四

void fork4()
{
   
    printf("L0\n");
    fork();
    printf("L1\n");
    fork();
    printf("L2\n");
    fork();
    printf("Bye\n");
}
int main(){
   
    fork4();
}

在这里插入图片描述
好的,我们可以数一数一共有一个L0,两个L1,四个L2,8个Bye,但因为进程独立,所以输出方式又有很多种啦,上面只是其中之一,列举如下的可能性(太多啦,只列举一些,大家只要记住上面的规则就可以都推出来的,完全是数学的排列组合问题嘛,o(╥﹏╥)o):

  1. L0 L1 L2 Bye Bye L1 L2 Bye Bye L2 Bye Bye L2 Bye Bye
  2. L0 L1 L2 Bye L1 Bye L2 L2 L2 Bye Bye Bye Bye Bye Bye
  3. L0 L1 L2 Bye L1 Bye L2 Bye Bye L2 Bye Bye L2 Bye Bye
  4. L0 L1 L2 Bye L1 Bye L2 Bye Bye L2 L2 Bye Bye Bye Bye
  5. L0 L1 L2 L2 Bye Bye Bye Bye L1 L2 L2 Bye Bye Bye Bye

实验五

void fork5()
{
   
    printf("L0\n");
    if 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值