linux fork函数浅析

linux fork函数浅析

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的差别是子进程的返回值是0,而父进程的返回值则是新进程(子进程)的进程 id。将子进程id返回给父进程的理由是:由于一个进程的子进程能够多于一个,没有一个函数使一个进程能够获得其全部子进程的进程id。 对子进程来说,之所以fork返回0给它,是由于它随时能够调用getpid()来获取自己的pid;也能够调用getppid()来获取父进程的id。(进程id 0总是由交换进程使用,所以一个子进程的进程id不可能为0 )。

fork之后,操作系统会复制一个与父进程全然同样的子进程,虽说是父子关系,可是在操作系统看来,他们更像兄弟关系,这2个进程共享代码空间,可是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也全然同样,子进程拥有父进程当前执行到的位置(两进程的程序计数器pc值同样,也就是说,子进程是从fork返回处開始执行的),但有一点不同,假设fork成功,子进程中fork的返回值是0,父进程中fork的返回值是子进程的进程号,假设fork不成功,父进程会返回错误。
能够这样想象,2个进程一直同一时候执行,并且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了。这也是fork为什么叫fork的原因

至于那一个最先执行,可能与操作系统(调度算法)有关,并且这个问题在实际应用中并不重要,假设须要父子进程协同,能够通过原语的办法解决。

 

一个fork样例

要搞清楚fork的运行过程,就必须先弄清楚操作系统中的“进程(process)”概念。一个进程,主要包括三个元素:
o. 一个能够运行的程序;
o. 和该进程相关联的所有数据(包含变量,内存空间,缓冲区等等);
o. 程序的运行上下文(execution context)。

最好还是简单理解为,一个进程表示的,就是一个可运行程序的一次运行过程中的一个状态。操作系统对进程的管理,典型的情况,是通过进程表完毕的。进程表中的每个表项,记录的是当前操作系统中一个进程的情况。对于单 CPU的情况而言,每一特定时刻仅仅有一个进程占用 CPU,可是系统中可能同一时候存在多个活动的(等待运行或继续运行的)进程。
一个称为“程序计数器(program counter, pc)”的寄存器,指出当前占用 CPU的进程要运行的下一条指令的位置。
当分给某个进程的 CPU时间已经用完,操作系统将该进程相关的寄存器的值,保存到该进程在进程表中相应的表项里面;把将要接替这个进程占用 CPU的那个进程的上下文,从进程表中读出,并更新相应的寄存器(这个过程称为“上下文交换(process context switch)”,实际的上下文交换须要涉及到很多其它的数据,那和fork无关,不再多说,主要要记住程序寄存器pc记录了程序当前已经运行到哪里,是进程上下文的重要内容,换出 CPU的进程要保存这个寄存器的值,换入CPU的进程,也要依据进程表中保存的本进程运行上下文信息,更新这个寄存器)。
好了,有这些概念打底,能够说fork了。当你的程序运行到以下的语句:pid=fork(); 

操作系统创建一个新的进程(子进程),而且在进程表中对应为它建立一个新的表项。新进程和原有进程的可运行程序是同一个程序;上下文和数据,绝大部分 就是原进程(父进程)的拷贝,但它们是两个相互独立的进程!此时程序寄存器pc,在父、子进程的上下文中都声称,这个进程眼下运行到fork调用即将返回(此时子进程不占有CPU,子进程的pc不是真正保存在寄存器中,而是作为进程上下文保存在进程表中的相应表项内)。问题是怎么返回,在父子进程中就分道扬镳。

(如果父进程一直占领CPU,实际情况非常可能不一样)父进程继续运行,操作系统对fork的实现,使这个调用在父进程中返回刚刚创建的子进程的pid(一个正整数),所以以下的swtich语句中运行了default分支(case -1,case 0分支都不满足)。所以输出I am the parent process…

子进程在之后的某个时候得到调度,它的上下文被换入,占领 CPU,操作系统对fork的实现,使得子进程中fork调用返回0,所以在这个进程(注意这不是父进程了哦,尽管是同一个程序,可是这是同一个程序的另外一次运行,在操作系统中这次运行是由另外一个进程表示的,从运行的角度说和父进程相互独立)中pid=0。这个进程继续运行的过程中,switch语句中 case -1不满足,可是case 0是满足。所以输出I am the child process..

 

程序的执行结果(先输出I am the parent process…,还是I am the parent process…)不可预见,与操作系统实际执行情况有关!

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

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

(0)
上一篇 2021年11月28日 下午2:00
下一篇 2021年11月28日 下午3:00


相关推荐

  • js获取当前时间标准格式_js获取当前时间年月日并输出

    js获取当前时间标准格式_js获取当前时间年月日并输出/** *获取当前时间格式:yyyy-MM-ddHH:MM:SS */functiongetCurrentTime(){   vardate=newDate();//当前时间   varmonth=zeroFill(date.getMonth()+1);//月   varday=zeroFill(date.getDate());//日   …

    2026年2月22日
    6
  • 基于Hmily实现TCC分布式事务解决方案[通俗易懂]

    基于Hmily实现TCC分布式事务解决方案[通俗易懂]前言在上一篇中,我们大致讲述了TCC事务的来源以及执行原理,并使用seata提供的解决方案完成了一个简单案例的整合与代码演示,本篇我们将采用Hmily的方式实现TCC事务的解决方案与演示业务描述有一个银行转账的场景,用户A需要向用户B转1块钱,如果大家使用的是同一个数据库,就不存在分布式事务的问题,现实中大家都各自使用自己的库,就产生了分布式事务可以理解为,两个账户分别在不同的银行(用户…

    2022年5月21日
    40
  • Java XML解析工具类

    Java XML解析工具类JavaXML解析工具类Java解析XML的方式有很多,这里不一一说明了,利用三方jar包,实现了一个XML工具类本身是有个需求,讲三方公司的XML请求文件中的Response里的属性赋值成java对象,没做完不需要了,只做到了解析,后续本来想利用解析出来的key进行遍历,利用FTL模板生成Java文件,有这个需求的小伙伴可以延续这个工具类。1.看看XML<?xmlversion=”1.0″encoding=”utf-8″?><!–每个协议有Request或Resp

    2022年7月21日
    16
  • JAVA获取服务器文件名乱码,java获取的文件名乱码问题

    JAVA获取服务器文件名乱码,java获取的文件名乱码问题java 获取的文件名乱码问题 2021 02 0911 22 59 简介 phpie 中文乱码的解决办法 首先判断下载文件的所有浏览器是否是 IE 浏览器 然后对文件名进行 urlencode 转义编码即可解决乱码问题 推荐 PHP 视频教程 解决 php 文件下载 IE 文件 php 上传文件名乱码的解决办法 首先打开 Upload html 文件 然后添加语句 enctype multipart f

    2026年3月26日
    2
  • server .mappath[通俗易懂]

    server .mappath[通俗易懂]1.Server.MapPath(“/”) 应用程序根目录所在的位置如C:/Inetpub/wwwroot/2.Server.MapPath(“./”) 表示所在页面的当前目录   注:等价于Server.MapPath(“”) 返回Server.MapPath(“”)所在页面的物理文件路径3.Server.MapPath(“../”)表示上一级目录4.Serve

    2022年7月12日
    29
  • navicat mac激活码-激活码分享

    (navicat mac激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~23LNPMIJZT-eyJsaWNlb…

    2022年3月29日
    101

发表回复

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

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