fork之后父子进程的内存关系
来源:互联网 发布:视频剪辑 for mac 编辑:程序博客网 时间:2024/04/19 21:36
1.fock()调用的基本语义
#include<unistd.h>pid_t fork(void);//父进程返回子进程的pid,子进程返回0,错误返回-1
fork()创建了一个心的进程(child)信进程几乎是调用进程(父进程的翻版),理解fork()的关键是,在完成对其调用之后,会产生2个进程,且每个进程都会从fork()的返回处开始执行.这俩个进程将执行相同的程序段,但是拥有各自不同的堆段,栈段,数据段,每个子程序都可修改各自的数据段,堆段,和栈段调用fork()之后先执行哪个进程的是由Linux下专有文件/proc/sys/kernel/sched_child_runs_first的值来确定的(值为0父进程先执行,非0子进程先执行)
2.fork()调用之后父子进程的内存关系
PS:建议读者在看这之前先看一下虚拟内存方面的知识,我的前几篇博文中就有从具体的表现形式(读者可写段代码测试)上看,我们会认为fork()是对父进程程序段,数据段,堆段,栈段的一个赋值,我们在表象上也的确可以这么理解早期的UNIX的fork()实现时,就是原汁原味的复制,和它的表像一样,但是很明显,这种方法效率太低,而且造成了很大的浪费,现在大部分的UNIX实现采用了如下俩种方法来规避这种浪费
(1)首先我们可以确定父子进程的代码段是相同的,所以代码段是没必要复制的,因此内核将代码段标记为只读,这样父子进程就可以安全的共享此代码段了。fork之后在进程创建代码段时,新子进程的进程级页表项都指向和父进程相同的物理页帧
(2)而对于父进程的数据段,堆段,栈段中的各页,由于父子进程要相互独立,所以我们采用写实复制的技术,来最大化的提高内存以及内核的利用率。刚开始,内核做了一些设置,令这些段的页表项指向父进程相同的物理内存页。调用fork之后,内核会捕获所有父进程或子进程针对这些页面的修改企图(说明此时还没修改)并为将要修改的页面创建拷贝。系统将新的页面拷贝分配给被内核捕获的进程,还会对子进程的相应页表项做适当的调整,现在父子进程就可以分别修改各自的上述段,不再互相影响了
写实复制前:
写实赋值后:
3.总结
表面看起来fork()创建子进程子进程拷贝了父进程的地址空间其实不然刚调用完fork()之后,子进程只是拥有一份和父进程相同的页表,其中页表中指向RAM代码段的部分是不会改变的,而指向数据段,堆段,栈段的会在我们将要改变父子进程各自的这部分内容时,才会将要操作的部分进行部分复制
0 0
- fork之后父子进程的内存关系
- fork 父子进程变量之间的关系
- fork之后父子进程的文件描述符
- fork()多次之后父子进程的数目变化
- malloc 之后的父子进程之间的空间关系如何
- fork 父子进程间信号关系
- 关父子进程关系fork()
- 关父子进程关系fork()
- 多进程 fork之后父子进程 对文件描述符的作用
- fork之后父子进程虚拟地址(逻辑地址)相同的问题
- 创建进程 fork()函数的基本使用 父子进程之间的关系
- fork vfork 父进程和子进程的内存关系
- fork()父子进程变量之间的关系与信号的响应
- Linux中fork()函数详解 父子进程变量的关系
- fork()后的父子进程
- 对fork()父子进程的一些理解
- 关于 fork 和父子进程的理解
- fork 和父子进程的理解
- 自定义控件-画板,橡皮擦,刮刮乐
- Spring整合 RMI
- 黑马程序员-----C语言学习之数组与指针
- POJ题目1947 Rebuilding Roads(树形dp)
- off格式文件解析
- fork之后父子进程的内存关系
- qt QLineEdit 左侧带自定义图标类
- wxSqlite给sqlite数据库添加口令
- 结构型模式-亨元模式
- Snail—OC学习之选择器SEL
- [LeetCode]Search a 2D Matrix II
- I2C总线和SPI总线
- mybatis 实现关联查询的一对多和多对多查询
- 方法内部lambda表达式中若用到变量,若在方法内lambda外,则只能为final,或者定义为全局变量