博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
fork()函数 —— 父子进程资源
阅读量:6921 次
发布时间:2019-06-27

本文共 1799 字,大约阅读时间需要 5 分钟。

fork()函数功能——创建新进程

1、父子进程有独立的数据段、堆、栈,共享代码段

  Linux中每个进程都有4G的虚拟地址空间(独立的3G用户空间和共享的1G内核空间),fork()创建的子进程也不例外。子进程资源的由来:

  1、1G内核空间既然是所有进程共享,因此fork()创建的子进程自然也将拥有;

  2、3G的用户空间是从父进程进程而来。

  fork()创建子进程时继承了父进程的数据段、代码段、栈段、堆,注意从父进程继承来的是虚拟地址空间,同时也复制了页表(没有复制物理块)。因此,此时父子进程拥有相同的虚拟地址,映射的物理内存也是一致的(独立的虚拟地址空间,共享父进程的物理内存)。

  由于父进程和子进程共享物理页面,内核将其标记为“只读”(类似mmap)的private的方式),父子双方均无法对其修改。无论父进程和子进程何时试图对一个共享的页面执行写操作,就产生一个错误,这时内核就把这个页复制到一个新的页面给这个进程,并标记为可写,同时修改页表,把原来的只读页面标记为“可写”,留给另外一个进程使用——写时复制技术。

  注意:内核在为子进程分配物理内存时,并没有将代码段对应的数据另外复制一份给子进程,最终父子进程代码段映射的是同一块物理内存(代码段在单个进程内部本来就是只读的)。  

  每个进程的虚拟地址空间都可以是0到4G,只不过其中只有一部分有权访问,每个进程可以有不同的映射。两次运行同一个程序就是使用的相同的虚拟地址,但是映射到的物理地却是不一样的。每个进程都有自己的虚拟地址空间,不同进程的相同的虚拟地址显然可以对应不同的物理地址。因此地址相同(虚拟地址)而值不同没什么奇怪。

写时复制技术参见:

2、一次调用两次执行

  参见:

3、 竞争条件

  Linux是一个多用户操作系统,在同一时间会有许多的用户在争夺系统的资源.有时进程为了早一点完成任务就创建子进程来争夺资源. 一旦子进程被创建,父子进程一起从fork处继续执行,相互竞争系统的资源.有时候我们希望子进程继续执行,而父进程阻塞,直到子进程完成任务.这个时候我们可以调用wait或者waitpid系统调用.

  对子进程来说,fork返回给它0,但它的pid绝对不会是0;之所以fork返回0给它,是因为它随时可以调用getpid()来获取自己的pid;fork之后父子进程除非采用了同步手段,否则不能确定谁先运行,也不能确定谁先结束。认为子进程结束后父进程才从fork返回的,这是不对的,fork不是这样的,vfork才这样。

4、fork之后跟随exec

  fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。由于写时复制,在fork之后exec之前两个进程有独立的虚拟地址空间,共享物理内存。只有其中一方需要写操作时,再为子进程的数据段、栈、堆分配物理空间。但在子进程上调用exec时,会清空栈、堆,以及和父进程共享的空间,重新加载新的代码段,这样避免了“写时复制”拷贝共享页面的机会,父进程也同时独自拥有了原来共享的物理内存(可对其读写操作)。

  fork出来子进程之后,父子进程哪个先调度直接决定了是否需要拷贝的问题?内核一般会先调度子进程,因为很多情况下子进程是要马上执行exec,而避免无用的复制。如果父进程先调度很可能写共享页面,会产生“写时复制”的无用功。所以,一般是子进程先调度滴。

  在网上看到还有个细节问题就是,fork之后内核会通过将子进程放在队列的前面,以让子进程先执行,以免父进程执行导致写时复制,而后子进程执行exec系统调用,因无意义的复制而造成效率的下降。

  如果不是因为exec,子进程执行时很可能修改内存,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。

 

5、fork()函数的实现过程

  

转载于:https://www.cnblogs.com/love-lzb/p/6833539.html

你可能感兴趣的文章
修改Windows7系统默认软件安装目录
查看>>
11-20 bom 浏览器对象模型
查看>>
回到基础:封装集合
查看>>
string转换成byte[]
查看>>
Canvas Frames
查看>>
【个人成长学习讨论小组】练习1:思维
查看>>
Navicat 远程连接 Oracle11g 数据库报错 No listener 的问题
查看>>
MFC 发送数据到SDK服务器
查看>>
post请求乱码
查看>>
java 两个时间字符串的时间差
查看>>
设计模式--建造者模式
查看>>
jquary 单选,多选,select 获取和设置值 jquary自定义函数
查看>>
实验6作业
查看>>
HTML5新增和废弃的标签
查看>>
从梯度下降法、最大间隔法两种角度理解SVM
查看>>
Leetcode | Reverse Nodes in k-Group
查看>>
算法导论: 第9章
查看>>
Dynamics CRM 2013 SP1 客户表单界面上联系人subgrid上的添加现有联系人功能缺失
查看>>
《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(4)--- 组件配置器...
查看>>
2012年11月9日学习研究报告
查看>>