linux下连续三次fork() –深度理解进程创建函数

linux下连续三次fork() –深度理解进程创建函数初识 linux 操作系统 fork 作为系统调用理解起来却并不是很容易 整理一下学习笔记 希望能对后来的初学者有所帮助 代码能说明问题 include lt stdio h gt include lt unistd h gt intmain pid tpid intcount 0 pid fork fork 一个进程

初识linux操作系统,fork作为系统调用理解起来却并不是很容易。


代码能说明问题

#include 
      #include 
      int main() { 
     pid_t pid; int count = 0; pid = fork(); //fork一个进程 if(pid == 0) { 
     //pid为0, printf("this is child process, pid is %d\n",getpid());//getpid返回的是当前进程的PID count+=2; printf("count = %d\n",count); } else if(pid > 0) { 
     printf("this is father process, pid is %d\n",getpid()); count++; printf("count = %d\n",count); } else { 
     fprintf(stderr,"ERROR:fork() failed!\n"); } return 0; } 

接下来问题就来了
fork的时候发生什么?
①执行到这一句的时候,一个进程被创建了,这个进程与父进程一样,拥有一套与父进程相同的变量,相同的一套代码,这里可以粗浅的理解为子进程又复制了一份main函数。这里返回一个子进程的进程号,大于0。(第一次fork)





②子进程怎么执行:

子进程从fork()的位置开始执行,也就是说前面的代码不走,但是拥有之前的变量以及变量的值,与父进程的值一样,这次fork(),返回值是0,所以在子进程里面直接执行了pid==0这一个分支,父进程里面并不执行这个分支的语句。这就为我们在写mian函数的时候怎么写子进程的程序提供了一个方法来隔离代码。


明白了这个原理之后我们再来看一段代码

#include 
     
       #include 
      
        int main() { pid_t pid[3]; int count = 0; pid[0] = fork(); pid[1] = fork(); pid[2] = fork(); printf("this is process\n"); return 0; } 
       
     

运行结果

这里写图片描述

这里每一次输出表示一个进程的创建,可以看到一共有8个进程被创建,有兴趣的话可以验证一下连续四次fork可以出16个进程,但是不建议再多了,电脑会卡死,不要问我怎么知道的!
猜想是出2的n次方个进程。如果上面的第一段代码理解了的话,我们按照子进程从父进程fork的位置开始执行就会理解为什么会有八个进程。

这里附上思维导图助于理解
这里写图片描述


那么我们想创建不是2的n次方个进程应该怎么做呢?这里还是以三个为例

#include 
      
        #include 
       
         #include 
        
          int main(int argc, char *argv[]) { int i,j,status; int pid[3]; for(i=0; i<3;i++){ if((pid[i]=fork()) >0){ printf("This is child process pid=%d\n",pid[i]); } else{ printf("This is father process pid=%d\n",pid[i]); exit( EXIT_SUCCESS); } } return EXIT_SUCCESS; } 
         
        
      

这里给出一个参考,不是最准确的,可以与三次fork进行对比

以上是原文


因为要找工作了,被迫重新复习了一下fork )

参考游双的《linux高性能服务器编程》

fork的时候


子进程的代码与父进程完全相同,同时它还会复制父进程的数据(堆数据、栈数据和静态数据)。数据的复制采用的是所谓的写时复制( copy on writte ),即只有在任一进程(父进程或子进程)对数据执行了写操作时,复制才会发生(先是缺页中断,然后操作系统给子进程分配内存并复制父进程的数据)。即便如此,如果我们在程序中分配了大量内存,那么使用fork时也应当十分谨慎,尽量避免没必要的内存分配和数据复制。


此外,创建子进程后,父进程中打开的文件描述符默认在子进程中也是打开的,且文件描述符的引用计数加1。不仅如此,父进程的用户根目录、当前工作目录等变量的引用计数均会加1。

所以子进程复制了父进程的代码段,并且程序拷贝了程序计数器,所以我们看到的子进程和父进程执行了相同的代码,有没有一种办法,可以让子进程执行自己的代码呢,是可以的,可以使用exec函数,将想执行的进程替换进来,然后exec函数会调用你载入进程的main函数。


感谢阅读!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214427.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午4:17
下一篇 2026年3月18日 下午4:17


相关推荐

  • vue笔记(2)vue中使用ajax

    vue笔记(1):https://blog.csdn.net/qq_43537987/article/details/93402865Vue中利用vue-resource发起Ajax请求除了vue-resource之外,还可以使用axios的第三方包实现实现数据的请求参考网址:https://www.runoob.com/vue2/vuejs-ajax.htmlhttp…

    2022年4月9日
    69
  • 阿里云矢量图标库用法_阿里矢量图库图标

    阿里云矢量图标库用法_阿里矢量图库图标1.登陆http://www.iconfont.cn/例如我需要购物车的图标2.按下回车后会出现一堆的购物车图标3.喜欢那个一个就鼠标移动到图标上去,加入购物车4点击加入购物车后,就会出现在右

    2022年8月1日
    8
  • 离散数学在计算机科学中的应用论文(集合论在计算机的应用)

    自从我们学院进行软件工程认证后,期末考试的专业课全部是大题。这次离散数学的最后一题是:利用本学期学到的离散数学的知识阐释其在一个软件工程中的应用。下面说说离散数学的应用。离散数学在数据结构中的应用数据结构中将操作对象间的关系分为四类:集合、线性结构、树形结构、图状结构或网状结构。数据结构研究的主要内容是数据的逻辑结构,物理存储结构以及基本运算操作。其中逻辑结构和基本运算操作来源于离散

    2022年4月17日
    121
  • cefsharp教程_flutter grpc

    cefsharp教程_flutter grpc需求注册常规快捷键比如F5刷新F12打开开发者工具; 自定义配置文件; 注册JavaScript交互API通过Winform调取设备或者系统数据; 屏蔽鼠标右键; 自定义文件下载功能; 集成自动更新服务;…

    2026年1月20日
    6
  • Dreamweaver8的安装

    Dreamweaver8的安装安装步骤:Step1:双击<Dreamweaver8-chs>Step2:单击<下一步>Step3:选中<我接受该许可证协议中的条款>,单击<下一步>按钮Step4:选中<在桌面上创建快捷方式(针对所有用户)>,单击<下一步>Step5:单击<下一步>S…

    2022年7月26日
    6
  • elk搭建与简单的线上应用

    elk搭建与简单的线上应用开源文档 Logstash https www elastic co guide en logstash current index htmlFilebeat https www elastic co guide en beats filebeat current index htmlElastics https www elastic co guide en elasticsearc reference current index htmlKibana https ww

    2026年3月26日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号