二、父子进程的关系

一、如何在进程中创建一个新的进程(fork函数)
1、pid_t fork(void);
(1)fork函数与别的函数有所不同,它调用一次,返回两次。在新创建出来的进程中返回一次(返回值为 0),在原来的进程中返回一次(返回值为新进程的pid)。
(2)fork函数调用完成以后,两个进程都从fork之后开始执行。
(3)fork函数复制出新的进程后,两个进程成为独立的个体,互相不影响,各自执行。并且哪个进程先执 行不一定。

2、先了解一下父子进程的定义:
通过fork函数创建的新进程是调用fork函数进程的子进程,而调用foek函数的进程为新进程的父进程。即就是,通过fork创建的进程与原进程之间时父子关系。
3、再了解两个函数:
getpid():用户获取调用getpid这个函数的进程的pid;
getppid():用户获取调用getppid这个函数的进程的父进程的pid;
4、孤儿进程:
当父进程结束以后,子进程未结束,子进程就是孤儿进程。这是子进程的父进程就变成init。
 init这个进程是守护进程,也叫孤儿院,负责处理这些孤儿进程推出以后的一些状态。
5、僵死进程(僵尸进程):父进程未结束,而子进程结束,父进程未获取子进程的推出数据,这时,子进程为僵尸进程。

6、fork之后,父子进程之间的数据是否共享呢?
全局数据、栈区数据、堆区数据是不共享的;
而父子进程对于文件描述符共享,并且共享文件偏移量。

 

pid_t fork(void); //父进程返回子进程的pid,子进程返回0,错误返回-1

fork()创建了一个新的进程(child),新进程几乎是调用进程(父进程)的翻版,理解fork()的关键是,在完成对其调用之后,会产生2个进程,且每个进程都会从fork()的返回处开始执行.

这俩个进程将执行相同的程序段,但是拥有各自不同的堆段,栈段,数据段,每个子程序都可修改各自的数据段,堆段,和栈段

父子进程的代码段是相同的,所以代码段是没必要复制的,因此内核将代码段标记为只读,这样父子进程就可以安全的共享此代码段了。fork之后在进程创建代码段时,新子进程的进程级页表项都指向和父进程相同的物理页帧


(2)而对于父进程的数据段,堆段,栈段中的各页,由于父子进程要相互独立,所以我们采用写实复制的技术,来最大化的提高内存以及内核的利用率。刚开始,内核做了一些设置,令这些段的页表项指向父进程相同的物理内存页。调用fork之后,内核会捕获所有父进程或子进程针对这些页面的修改企图(说明此时还没修改)并为将要修改的页面创建拷贝。系统将新的页面拷贝分配给被内核捕获的进程,还会对子进程的相应页表项做适当的调整,现在父子进程就可以分别修改各自的上述段,不再互相影响了
写实复制前: 


写实赋值后: 

 

二、数据共享

  我们现在通过一段代码研究一下父子进程的是否存在数据共享。

  我们现在简单把数据分成三种:堆区数据、栈区数据、全局数据。所以我现在有三个变量,同时,我让子进程改变这三个变量的值。让父进程沉睡两秒钟以确保子进程运行结束。

  结果如下:

  可以看到,其值发生了改变,这也说明,

      父子进程的堆区数据、栈区数据、全局数据是不共享的。

  


 

  那子进程能和父进程共享文件吗?我们看看以下代码:

  我先open一个我创建好的在同一目录下的a.txt文件,a.txt文件中我写了“Hello World!”

  让父子进程一起一个字节一个字节的读文件里字符,每读一次sleep一秒钟。

  结果如下:

  这是什么呢,这就是说,并不是一个进程操作一个文件时,另一个进程就不能操作,而且,父子进程可以同时操作同一个文件。

  也就是,

       在父子进程中,文件描述符以及文件偏移量,都是共享的!


   为什么文件就能共享了呢,在linux源码里,每个进程都有一个PCB(进程控制块)结构体,每个PCB里,存了一个结构体指针指向一个我们理解为文件描述符的结构体struct file,而这个结构体里,才存了文件的id,从什么地方开始写,模式等等。值得注意的事,这个结构体里有一个指针才是指向真正的文件的。

 

参考:https://www.cnblogs.com/jian-99/p/7719085.html

http://blog.sina.com.cn/s/blog_1550922e60102z7gm.html

https://blog.csdn.net/shreck66/article/details/47039937

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值