操作系统fork()进程

操作系统fork()进程1 fork 是创建进程函数 2 c 程序一开始 就会产生一个进程 当这个进程执行到 fork 的时候 会创建一个子进程 3 此时父进程和子进程是共存的 它们俩会一起向下执行 c 程序的代码 4 需要注意 子进程创建成功后 fork 是返回两个值 一个代表父进程 一个代表子进程 代表父进程的值是一串数字 这串数字是子进程的 ID 地址 一个代表子进程 值为 0 下面写一段代了

1、fork()是创建进程函数。

2、c程序一开始,就会产生 一个进程,当这个进程执行到fork()的时候,会创建一个子进程。

3、此时父进程和子进程是共存的,它们俩会一起向下执行c程序的代码。

4、需要注意!!!子进程创建成功后,fork是返回两个值,一个代表父进程,一个代表子进程:代表父进程的值是一串数字,这串数字是子进程的ID(地址);一个代表子进程,值为0。

下面写一段代了解了解(注释很重要)
在这里插入图片描述
运行结果如下父进程printf出来的是子进程 的ID即那串数字,子进程printf的则为0:
在这里插入图片描述






深入学习

1-1.c

#include 
  
    #include 
   
     int main() { int p1,p2; if(p1=fork()) /*子进程创建成功*/ //父进程返回的是一串数字>1,满足条件,执行下面语句 putchar('b');//首先输出b,之后该父进程自杀了(结束) else //这里是由于子进程的fork为0,子进程在这里面执行 { if(p2=fork()) //在这里子进程创建了自己的子进程(先凑合叫做孙进程吧),此时子进程fork返回孙进程的ID>1,则可以执行下面语句 putchar('c');//子进程执行,输出c else putchar('a'); /*父进程执行*/ //上面老师注释的父进程我认为是“孙进程”,而不是一开始的父进程,一开始的父进程putchar出b后,已经被杀死了,不信可以 printf("%d",p2);,看看是不是输出0,fork()为0,则为孙进程 } printf("\n"); } 
    
  

执行结果(注意看代码注释,通俗点说就是父进程输出了b,子进程输出了c,孙进程输出a 。其实没有孙进程这种说法吧。)
在这里插入图片描述

1-2.c

#include 
  
    #include 
   
     #include 
    
      int main() { int p1,p2; while((p1=fork())==-1)//如果子进程创建失败则fork返回-1=-1,while循环不会跳出,直至创建成功,fork为子进程的ID或者0才可以跳出while循环 printf("111"); //没有输出111.说明p1不等于-1,那说明子进程创建成功,直接跳出while循环 // printf("%d\n",p1); //父子进程都会执行这一句,谁先谁后是随机的,所以有可能先显示0再显示ID,否则反之 if (p1==0) //子进程的fork为0,满足此条件 putchar('b'); //由子进程输出‘b’,接着子进程自杀 else //由于刚刚父进程不满足上面的if条件,所以来到else这下面执行 { while((p2=fork())==-1); //重建子进程(第二个孩子) if (p2==0) //第二个孩子满足fork=0 putchar('c'); //第二个孩子执行输出“c” else //父进程最终什么都不满足地来到这里 {putchar('a'); //父进程输出“a” //printf("\n%d\n",p2); } } }//结果我猜正确的顺序是acb或者bac。这个要看父子进程的看快慢,就像赛跑。 
     
    
  

执行结果
在这里插入图片描述

2-1.c

#include 
  
    #include 
   
     int main() { int p1,p2,i; if(p1=fork())//此时父进程的fork为一串数字,子进程fork为0;父进程的fork>0,满足条件 for(i=0;i<5;i++) printf("child %d\n",i);//说明创建进程成功,不管是男孩还是女孩 else//子进程不满足上面if条件,从而来到这里 { if(p2=fork())//子进程来这里创建“孙”进程,此后子进程fork为一串数字即“孙”进程的ID;则孙进程的fork为0;子进程fork>0,满足条件 for(i=0;i<5;i++) printf("son %d\n",i); else//“孙”进程不满足上面if条件,从而来到这里 for(i=0;i<5;i++) printf("daughter %d\n",i);//老师的理解和我的不一样吧。我认为这是子进程的子进程了,是个女儿。 } } //输出结果的话,也是随机的 
    
  

执行结果:
在这里插入图片描述
2-2.c




/* author:Szymou explain: lockf(1,1,0)是锁上资源让该进程独自享用 lockf(1,0,0)是解锁资源,给其他进程用 下面的sleep用于该进程“休息一下”,休息的时候,其他进程可以用资源 这里的资源是个人认为是磁盘的缓冲区buffer */ #include 
  
    #include 
   
     int main()//每次printf的时候,系统会先将需要输出的字符存在缓冲区buffer里面 { int p1,p2,i; if(p1=fork()) { lockf(1,1,0);//锁上buffer自己享用 for(i=0;i<3;i++) { printf("child %d\n",i); /*老师的默认第二个lockf(1,1,0)是一直锁上的,结果会是先全部输出son012,再输出其他,其他进程同理*/ lockf(1,0,0);//解锁给另外的子进程 sleep(2);//其他子进程可以在父进程休眠的时候调用buffer使用 } } else { if(p2=fork()) { lockf(1,1,0);//锁上buffer自己享用 for(i=0;i<3;i++) { printf("son %d\n",i); lockf(1,0,0); sleep(2); } } else { lockf(1,1,0);//锁上buffer自己享用 //运行结果>>>>> for(i=0;i<3;i++) //运行结果>>>>> { printf("daughter %d\n",i); lockf(1,0,0); sleep(2); } } }return 0; } 
    
  

运行结果:
在这里插入图片描述
3-1.c




/* author:Szymou explain: 父进程称为a进程 往下就是b、c、d进程 */ #include 
  
    #include 
   
     int main() { int p1,p2,p3,p4; while((p1=fork())==-1);//a进程在这里创建b进程 if(p1!=0)//父进程称为a进程,进来了 { printf("process a(its id=%d,its father pid is %d)\n",getpid(),getppid()); } else//b进程进来了 { printf("precess b(its id=%d,its father pid is %d)\n",getpid(),getppid()); while((p2=fork())==-1) ;//b进程创建c进程 if(p2==0)//c进程进来 { printf("precess c(its id=%d,its father pid is %d)\n",getpid(),getppid()); while((p3=fork())==-1) ;//c进程创建d进程 if(p3==0)//d进程进来 printf("precess d(its id=%d,its father pid is %d)\n",getpid(),getppid()); } } return 0; } 
    
  

观察执行结果,会发现有些进程的父进程ID显示不是自己父进程的ID 这是因为其父进程死了,而她成了孤儿进程,被某进程收养了,所以显示的父进程ID是收养它的那个进程的ID,可以用命令ps
x查看当前进程,查找进程ID,即可明了。
在这里插入图片描述




应该怎么使得每个进程的父进程ID显示正确呢?
那就应该让该父进程别死,让它等待其子进程死后再死即可。这时候我们就应该使用一个函数了,这个函数是wait()。
作用是父进程执行到wait(),会被挂起来,等待其子进程结束后,自己才结束。




代码:

/* author:Szymou explain: 父进程称为a进程 往下就是b、c、d进程; 有一种情况:有些进程显示其父进程ID不是父进程ID,而是系统进程ID,这是因为父进程死后,子进程get不到父进程ID,从而成了孤儿,在乌班图下会被upstart收养,在CentOS下会被init收养。可以用ps x来查看; wait()函数可以让当前父进程等待子进程结束,父进程才结束。这里引进这个函数,是因为,避免父进程死后,子进程没了爸爸,找不到爸爸的ID即getppid */ /* 这两个头文件用于支持wait()函数 */ #include 
  
    #include 
   
     #include 
    
      #include 
     
       int main() { int p1,p2,p3,p4; while((p1=fork())==-1);//a进程在这里创建b进程 if(p1!=0)//父进程称为a进程,进来了 { printf("process a(its id=%d,its father pid is %d)\n",getpid(),getppid()); wait(NULL); } else//b进程进来了 { printf("precess b(its id=%d,its father pid is %d)\n",getpid(),getppid()); while((p2=fork())==-1) ;//b进程创建c进程 if(p2!=0) wait(NULL); //sleep(1); else if(p2==0)//c进程进来 { printf("precess c(its id=%d,its father pid is %d)\n",getpid(),getppid()); while((p3=fork())==-1) ;//c进程创建d进程 if(p3!=0) wait(NULL); //sleep(1); else if(p3==0)//d进程进来 printf("precess d(its id=%d,its father pid is %d)\n",getpid(),getppid()); } } return 0; } 
      
     
    
  

运行结果(不再会出现孤儿进程现象)
在这里插入图片描述

有什么问题可以在评论区一起讨论哦!一起学

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

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

(0)
上一篇 2026年3月26日 下午1:41
下一篇 2026年3月26日 下午1:41


相关推荐

  • vue上传文件流

    vue上传文件流创建formData方法,把文件流以及所有需要上传的数据通过formData.append传入formData中,上传请求中的data中只需要放一个formData就可以了。(此处request为封装的请求方法,省事可以不封装)

    2022年10月16日
    7
  • coff格式

    coff格式COFF 通用对象文件格式 CommonObject 是一种很流行的对象文件格式 注意 这里不说它是 目标 文件 是为了和编译器产生的目标文件 o obj 相区别 因为这种格式不只用于目标文件 库文件 可执行文件也经常是这种格式 大家可能会经常使用 VC 吧 它所产生的目标文件 obj 就是这种格式 其它的编译器 如 GCC GNUCompilerC

    2026年3月17日
    1
  • ElasticSearch搜索引擎:常用的存储mapping配置项 与 doc_values详细介绍

    ElasticSearch搜索引擎:常用的存储mapping配置项 与 doc_values详细介绍

    2021年10月5日
    56
  • vscode引入vue_vscode配置vue开发环境

    vscode引入vue_vscode配置vue开发环境vs导入vue项目renren-fast-vue使用

    2022年7月28日
    5
  • 经典网页设计:25个优秀的个人网站设计欣赏

    经典网页设计:25个优秀的个人网站设计欣赏个人网站是让人们知道你 了解你生活中成就的最佳方式 有些人选择最搞笑的言论表达自己的想法 有的人则充分展现自己的个性 不管采用什么方式呈现你的个人网站 重要的是 把你最好的一面表现出来 下面是一些帮助你制作成功的个人网站的很有用的例子 CatRabbit nbsp CMYK08 nbsp MeandMyAAA nbsp MarkLaw

    2026年3月19日
    2
  • JMM内存模型介绍「建议收藏」

    JMM内存模型介绍「建议收藏」一、JMM的定义1.什么是JMM《Java虚拟机规范》中曾试图定义一种“Java内存模型”(JavaMemoryModel简称JMM)来屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。Java内存模型是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。JMM是围绕原子性,有序性、可见性展开。2.主内存与工作内存Java内存模型的主要目的是定义程

    2025年7月14日
    6

发表回复

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

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