fork总结

fork作用

fork可以用来创建一个新的进程。

fork声明

这里写图片描述

fork特性

  1. fork调用一次,返回两次:
    1)返回0给子进程
    2)返回子进程的进程ID给父进程
  2. 父子进程的先后执行顺序是不确定的,这个取决于内核的调度算法
  3. 子进程只是父进程的一份拷贝,子进程会复制父进程的数据空间、堆、栈。它们不会共享这部分内容,只会共享正文段(正文段,可以把它理解成一块专门存储代码的内存)

下面通过三个例程来说明fork的特性

demo1

      1 void demo1(void)                                                                                                                  
      2 {
      3     pid_t pid;
      4     int val = 0;
      5     
      6     if( (pid=fork()) < 0)
      7     {
      8         printf("fork fail\n");
      9     }   
     10     else if(0 == pid)       // This is children process
     11     {
     12         val = 50;
     13         printf("This is children, parent pid:%d, current pid:%d, pid:%d\n", getppid(), getpid(), pid);
     14     }   
     15     else                   // This is parent process
     16     {
     17         val = 100;
     18         printf("This is parent, parent pid:%d, current pid:%d, pid:%d\n", getppid(), getpid(), pid);
     19     }   
     20     
     21     printf("pid:%d, val:%d\n", getpid(), val);
     22 } 

程序运行的结果如下

This is parent, parent pid:2908, current pid:3164, pid:3165
pid:3164, val:100
This is children, parent pid:1, current pid:3165, pid:0
pid:3165, val:50

分析demo1的代码和运行结果

从运行结果看,第13行的打印输出了,而且第18行的打印输出了,平时我们看到的code,一般if和else只会跑其中一个,但是这里跑了两次。说明fork调用一次,返回两次,所以else if(0 == pid)和else这两种情况都会跑进去。

从代码和运行结果看,打印显示父进程中pid:3165,子进程中current pid:3165, pid:0 ,fork之后,有两个返回值,返回0给子进程,返回子进程的ID给父进程。

运行结果显示的是先打印parent,再打印children,但是这个打印是不确定的,有可能是先打印children,再打印parent。有的人可能会想,如果我在parent打印前加个sleep(1)或者spleep多秒,这样是不是就保证了children会先打印呢?这个不好说,即使在parent打印前sleep多秒,系统还是有可能先打印children,这个要根据系统的调度算法。

从运行结果看,parent和children的val值都是自己最先设定的值,这说明了子进程只是父进程的一个拷贝,子进程将父进程的数据空间、堆、栈都拷贝了一份,而不是共享。所以这里val的值大家互不干涉。

demo2

  1 void demo2(void)                                                                                                                   
  2 {
  3     printf("l1\n");
  4     fork();
  5     printf("l2\n");
  6     fork();
  7     printf("l3\n");
  8 }   

程序运行的结果如下

l1
l2
l3
l2
l3
l3
l3

分析demo2的代码和运行结果

程序跑到第3行的时候,会打印出l1

当程序跑到第4行fork之后,会创建出一个父进程A和一个子进程B,因为子进程是父进程的一份拷贝。也就是说,父子进程都会包含剩下的正文段(代码),即都包含第5行到第8行的代码。那么,接下来,父子进程都会跑第5行的代码,也就是各自打印出l2

接下来,主要讲父进程A怎么跑的,因为父子进程跑的内容是一样的。程序运行到第6行的时候,又fork了一次,父进程A里又创建了一个父进程C和子进程D,父(C)子(D)进程都包含第7行代码,所以父进程(C)和子进程(D)都会打印出l3.

因为父进程A和子进程B执行的是一样的内容,所以父进程A创建的进程C和进程D,会打印出两个l3,子进程B也是一样会打印出两个l3.

可以通过下图更直观地了解,打印的顺序看具体的系统调度算法。
这里写图片描述

demo3

  1 void demo3(void)                                                                                                                  
  2 {
  3     printf("l1\n");
  4     fork();
  5     printf("l2\n");
  6     fork();
  7     printf("l3\n");
  8     fork();
  9     printf("l4\n");
 10 }

程序运行的结果如下

l1
l2
l3
l2
l4
l3
l4
l3
l4
l4
l4
l3
l4
l4
l4

分析demo3的代码和运行结果

其实demo3和demo2很像,刚开始都会打印出l1,遇到第一个fork,就会创建一个父进程A和子进程B,进程A和B都会拷贝第5行到第9行的代码

那么接下来父(A)子(B)进程都会打印出l2,遇到第二个fork,父(A)子(B)进程各自都会创建新的父子进程,以此类推,直接用图来表示

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值