fork之后父子进程的内存关系

fork父子进程笔记 笔记: 创建进程 #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> int main(int argc, char* argv[]) { pid_t id; id = fork(); int i = 0; if(id < 0) { perror("fork"); exit(1); } else if 阅读详情

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代码段的部分是不会改变的,而指向数据段,堆段,栈段的会在我们将要改变父子进程各自的这部分内容时,才会将要操作的部分进行部分复制
Copy-On-Write COW 技术简介 COW技术初窥:       在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。      那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢?       在fork之后exec之前两个进程用的是相 阅读详情

相关推荐

Linux中父子进程关系与动态内存分配示例

通过使用malloc()函数,我们可以在程序运行时动态地分配内存,而不需要在编译时知道需要分配多少内存。在Linux操作系统中,进程是执行中的程序的实例。在Linux中,一个进程可以通过fork()系统调用创建一个新的子进程子进程父进程的副本,它继承了父进程的所有资源和状态。需要注意的是,在程序结束之前,我们使用free()函数释放了通过malloc()函数动态分配的内存。在这个示例程序中,我们首先使用malloc()函数动态分配了一个整数的内存空间,并将其存储在指针变量。的值,并对其进行修改。

CyberXZ的博客 228

冷月手撕408之操作系统(5)-进程概述

操作系统的进程概述主要是介绍了进程的概念,进程的组成(进程实体)、进程的特征、进程的五状态模型、进程控制,其中重点掌握PCB、五状态模型及其状态转换。 主要的重点冷月做出了标识,知识点如下图(pdf版或xmind源文件请关注公众号:学长冷月,回复操作系统)。 冷月点睛 程序是静态的存储在计算机硬盘里面的计算机代码,而进程是程序在数据上的一次动态执行。 进程实体也叫进程映像,包括程序段、数据段、PCB。是进程的静态组成。 PCB,进程控制块,进程存在的唯一标识,常驻内存中。 进程最主要、最基本的特征是动态性

学长冷月的博客 2208

Linux编程:fork父子进程内存

linux编程中,通过fork函数会创建子进程,创建后根据写时复制策略,父子进程是共享父进程的堆与栈,当父子进程中的一方对内存进行了写操作后,父子进程内存会分离,各自拥有自己独立的内存: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #define STR_SIZE 30 void doInChild(char *str) { pri

风静如云的博客 1601

fork()之后,发生了什么?

我们都知道,在Linux中调用fork()函数,会创建一个子进程,那么在创建这个子进程的过程中,发生了些什么事情? 首先,我们要知道,fork()函数其实是调用发起_fork()系统调用,控制权由用户态转为内核态, 内核会分配新的内存块和内核数据结构给子进程(也就是PCB task_struct结构体), 然后内核会将父进程的部分数据内容以二进制形式拷贝到子进程, 下来再将所谓的子进...

有没有兴趣和我一起去拯救地球啊 1492

linux中fork()函数详解(原创!!实例讲解)

一、fork入门知识 二、fork进阶知识 三、fork高阶知识

jason的专栏 44万+

C语言 父进程fork()出的多个子进程在结束后,父进程如何回收?

我在网上找了半天都是在说wait()和waitpid()的详解或者是单个子进程的回收。答非所问。 很简单,根据wait()或者waitpid()的函数特性。没有子进程时返回-1。 while(-1 != wait(NULL)) { } //另:因为waitpid(pid_t pid,int*status,int options)函数不提供返回无子进程的值,也就是出错。 while...

ALex_zry的博客 2346

linux系统编程之进程创建实战,fork与vfork创建进程的区别

1.首先我们先来了解一下fork创建进程: (1)使用fork函数创建一个进程,pid_t fork(void), fork函数调用成功的话,返回两次 返回值为0, 代表当前进程是子进程。 返回值为非负数,代表当前进程是父进程。 调用失败的话,返回-1。 重要提示:调用fork函数时,父进程的返回值就是子进程的进程ID,而子进程的返回值是0; (2)fork函数创建一个子进程的一般目的 (3)fork编程实战 (4)直接上代码 #include <stdio.h> #in

weixin_51976284的博客 465

【Linux】——进程创建fork()详解

文章目录一、fork作用二、fork()特性1、父子进程之间的关系2、父子进程返回情况3、父子进程执行情况三、写时拷贝技术1、概念2、特点 一、fork作用 我们都知道fork可以用于进程的创建,那首先我们来了解一下fork的两种用法才真正的了解我们何时才会用到fork来进行进程的创建 用法一:一个父进程希望复制自己,使父、子进程同时执行不同的代码段。 这在网络服务进程中是最常见的——父进程等待客...

qq_43412060的博客 1万+

重学计算机(八、进程与创建进程)

在程序是怎么运行中,也讲到进程,但由于篇幅和主题原因,并没有详细介绍;这一次,就要好好介绍一下进程,进程这个概念很多,并且也是操作系统的核心。

酱油师兄的博客 863

LINUX编程学习笔记(十四) 创建进程与 父子进程内存空间

1什么是进程:进程是一个执行中的程序 执行的程序: 代码->资源->CPU 进程有很多数据维护:进程状态/进程属性 所有进程属性采用的一个树形结构体维护 ps  -a//所有进程 ps -aue //有效进程       进程状态:(man ps)        D    Uninterruptible sleep (usually IO)        R

1255

fork

说到 fork ,大家应该都知道它的作用是从已经存在的进程中创建一个子进程。 可是这个过程中 fork 到底做了什么呢? 让我们来看看一个简单的程序。 #include <stdio.h> #include <unistd.h> int main() { fork(); printf("a\n"); return 0; } 这个程序运行结果为 a a 大家应该都...

qq_36147009的博客 286

Linux C++基础--fork()

创建新进程成功后,系统中出现两个基本完全相同的进程,子进程父进程处继承了整个进程的地址空间,包括进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端,父子进程不共享这些存储空间部分,父子进程共享正文段。进程2的变量为count=0,pid=0(子进程),这两个进程的变量都是独立的,存在不同的地址中,不是共用的,这点要注意。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

顺其自然~专栏 1032

fork后的父子进程

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

jwy2014的专栏 1481

fork()函数创建子进程

APUE–fork()函数介绍 文章目录APUE--fork()函数介绍一、fork()系统调用介绍1.fork()创建子进程特点2. 子进程的特点二、代码示例1.fork()创建子线程2.子进程内存修改 一、fork()系统调用介绍 1.fork()创建子进程特点 fork()用于创建子进程,一次调用会有两个返回(return),一次返回给父进程子进程的PID(Process ID),一次返回给子进程,其返回值为0. 返回值=0,子进程在运行 返回值>0,父进程在运行 返回值<0,fo

qq_47834139的博客 7216

Linux相关命令之进程

Linux查看进程查看进程 查看进程 netstat -tulpn

weixin_41756573的博客 527

linux的fork-父进程子进程关系

当一个父进程退出时,如果它有子进程,这些子进程将成为“孤儿进程”,并由 init 进程(PID 为 1)接管。子进程父进程的一个副本,它继承了父进程的许多属性,例如打开的文件描述符、信号处理设置等,但是它有自己的唯一进程ID(PID)和内存空间。父进程还会打印出子进程的PID。然后,可以编写一个外部脚本或程序来监视父进程的状态,并在父进程退出时读取 PID 文件,并向子进程发送信号。:如果父进程创建了一个新的会话,并且子进程是这个会话的成员,那么当父进程退出时,子进程可能会收到 SIGHUP 信号。

玖拾说架构 1156

操作系统理解 | 进程概念 | fork创建子进程

操作系统概念理解,进程的概念,在Linux系统下使用系统调用接口创建进程!

qq_63159859的博客 1359

fork之后子进程父进程关系

#include #include #include #include void main() { char str[6]="hello"; pid_t pid=fork(); if(pid==0) { str[0]='b'; printf("子进程中str=%s\n",str); printf("子进程中str指向的

mfcheer 4799
上一篇: TCP/IP协议学习笔记(4)--ICMP协议
下一篇: TCP/IP详解学习笔记--UDP协议
Shreck66
博客等级 码龄11年 118粉丝 91原创
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值