Linux 进程的地址空间

一、进程

进程:是一个正在运行的程序

PCB : 即是进程控制块,是进程存在的唯一标志。用来描述进程的属性信息,如进程的pid。

在这里插入图片描述
每一个进程都是通过fork复制而来的。

在执行fork之后,先将PCB复制一份给子进程,复制之前先申请一个pid,将复制给子进程的PCB中的pid修改为申请成功的pid;然后把当前的进程复制一份给子进程。父子进程并发运行。

二、进程的地址空间

以32位为例:

在32位的计算机系统中进程的地址空间是4G,如下图所示:

在这里插入图片描述

通常定义一个空指针时int *p = NULL;,这个指针p指向的空就是指向的上图中的0x0000 0000

地址空间除了内核使用的1G,剩下的3G实际上能用的内存空间是小于3G的。

虽然一个进程的地址空间为4G,但是实际上在执行一个程序的时候并不会把4G的内存空间用完,其中代码段和数据段使用几个页面就足够了,而一个页面的内存是4K,所以执行一个程序实际上用到的内存比4G小很多,所以并不是16G的计算机只能运行4个进程。这个4G是规定一个进程最大占用4G的内存空间,也就是一个进程理论上拥有4G地址空间的权限,一般情况下不会用完。

在地址空间中,代码段是从0x0804 8000开始,是一个固定值:

在这里插入图片描述

内核和用户使用空间的分界线的上限为0xc000 0000,下限为0xbfff ffff

在这里插入图片描述

1.定义在栈上的变量

由于栈是从上往下增长,所以在栈上定义的局部变量的地址就离0xbfff ffff非常接近。在栈上定义的变量每次运行的地址是不一样的,每次运行程序栈在分配的时候故意让局部变量的地址不一样,以确保程序的安全性。

2.在堆上申请动态内存

(1)malloc申请的内存空间当程序结束后会被系统自动回收

在Linux中,用malloc申请一块1G的内存空间,不用free释放也可以,不会发生内存泄漏,因为进程终止之后,所申请的内存空间就会被回收,但是当进程运行的时间长时,也是需要用free来释放的。在C语言中,malloc分配一段内存空间之后必须用free释放掉这块内存空间,不然会发生内存泄露。但是,我们一般在使用malloc之后是需要通过free释放空间的。

(2)malloc能申请多大的内存空间

32位系统内存空间的理论值小于3G,参考地址空间,如上图。

①当物理内存剩余的内存空间大于要申请的内存空间的时候是可以申请成功的。

比如现在物理内存剩余的内存空间为1.8G,要用malloc申请1G的内存空间是可以申请成功的。

②当前物理内存剩余的空间加虚拟内存剩余的空间能否满足申请要求。

当malloc申请内存2G内存空间,当物理内存剩余的空间加虚拟内存剩余的空间大于2G,就可以申请成功。如果分配在虚拟内存的空间不去使用,那么它就一直在虚拟内存,不会被调用回物理内存。如果物理内存的剩余空间加上虚拟内存的剩余空间不能满足申请内存空间的要求,那就申请失败,这里的满足还要考虑自身的特性,自身最多只能申请接近3G。如果没有虚拟内容就会申请失败。

③当前物理内存剩余的空间加虚拟内存剩余的空间比所申请的空间大,但是申请失败。

当malloc申请3G的内存空间,虽然物理内存和虚拟内存加起来超过了3G,但是不会申请成功,因为用户可以使用的内存空间为3G,除去代码段、数据段之后留给堆区的内存空间是不够3G的。用户最多只能申请接近3G

④malloc 与 fork,父进程堆区申请的空间复制后,子进程也会有一份,也需要释放吗?

父子进程对申请的堆空间都没有操作,代码如下:

在这里插入图片描述

父进程在堆区申请了5个字节大小为int型的内存,通过fork复制之后,产生一个子进程,并在父进程和子进程结束前都执行了free。

编译以上代码,并运行,编译运行并没有出错:

在这里插入图片描述

所以,我们可以知道,父进程在堆区申请的内存空间复制一份给子进程之后,子进程并不共享父进程的内存空间,父子进程在堆区都会有一份内存空间。因为如果这段内存空间是共享的,那么父进程对这段内存空间free一次,子进程再对这段内存空间free一次,对同一个内存空间free两次,编译运行会出现错误。而此时编译运行并没有出错,所以父子进程堆空间不共享(这里指的是每个进程的堆空间),哪怕父子进程对申请的堆空间都没有操作。

现在父子进程对申请的堆空间进行操作,代码如下:

在这里插入图片描述
上述代码,让子进程中的arr[0]等于10,让父进程中的arr[1]等于100。

编译并运行以上代码,结果如下:

在这里插入图片描述

结果分析:输出的结果中,第一行是父进程输出的结果,第二行是子进程输出的结果,可以看出父子进程对堆空间里的值进行修改,父进程对堆空间的值进行修改并没有导致对应子进程堆空间的值被修改,子进程对堆空间的值进行修改也没有导致对应父进程堆空间的值被修改。更加可以说明,父子进程是不共享堆上的内存空间的。子进程也需要释放从父进程复制过来的堆上的内存空间。

malloc申请的空间是对每个进程的物理地址而言的,只有当用到申请的空间,才会映射到底层真时物理地址。

【注意】

同一个程序在每次运行的时候,代码的逻辑地址不会变,物理地址会变,但是物理地址我们看不到,我们能看到的打印出来的地址都是逻辑地址。

如果一个函数没有被主函数调用也会给该函数分配内存空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/69164.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lab2 system calls

目录 PreRead任务列表4.3 Code: Calling system calls4.4 Code: System call arguments System call tracing测试任务hints思路先看用户的trace函数trace系统调用到底是怎么作用的呢? 重新捋一遍系统调用的过程 Sysinfo任务hints思路 PreRead 任务列表 xv6课本 第二…

【C#】静默安装、SQL SERVER静默安装等

可以通过cmd命令行来执行&#xff0c;也可以通过代码来执行&#xff0c;一般都需要管理员权限运行 代码 /// <summary>/// 静默安装/// </summary>/// <param name"fileName">安装文件路径</param>/// <param name"arguments"…

单片机串口通讯实战:详解STM32的串口编程与数据传输

引言&#xff1a; 单片机串口通讯是应用非常广泛的通讯方式&#xff0c;具有简单、灵活、稳定等特点。本文将深入探讨单片机串口通讯的原理、应用和性能优化&#xff0c;同时介绍如何使用STM32单片机进行串口编程&#xff0c;并提供详细的代码示例和注释。 一、单片机串口通讯…

大数据课程I4——Kafka的零拷贝技术

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握Kafka的零拷贝技术&#xff1b; ⚪ 了解常规的文件传输过程&#xff1b; 一、常规的网络传输原理 表面上一个很简单的网络文件输出的过程&#xff0c;在OS底层&…

LeetCode 0833. 字符串中的查找与替换

【LetMeFly】833.字符串中的查找与替换 力扣题目链接&#xff1a;https://leetcode.cn/problems/find-and-replace-in-string/ 你会得到一个字符串 s (索引从 0 开始)&#xff0c;你必须对它执行 k 个替换操作。替换操作以三个长度均为 k 的并行数组给出&#xff1a;indices,…

Keil开发STM32单片机项目的三种方式

STM32单片机相比51单片机&#xff0c;内部结构复杂很多&#xff0c;因此直接对底层寄存器编码&#xff0c;相对复杂&#xff0c;这个需要我们了解芯片手册&#xff0c;对于复杂项目&#xff0c;这些操作可能需要反复编写&#xff0c;因此出现了标准库的方式&#xff0c;对寄存器…

【解决】Kafka Exception thrown when sending a message with key=‘null‘ 异常

问题原因&#xff1a; 如下图&#xff0c;kafka 中配置的是监听域名的方式&#xff0c;但程序里使用的是 ip:port 的连接方式。 解决办法&#xff1a; kafka 中配置的是域名的方式&#xff0c;程序里也相应配置成 域名:port 的方式&#xff08;注意&#xff1a;本地h…

安卓13解决链接问题

作为Android用户&#xff0c;你可能已经注意到了一个问题——Android 13不再支持PPTP协议。但请别担心&#xff0c;作为一家专业的代理供应商&#xff0c;我们将与你分享解决方案&#xff0c;让你轻松解决L2TP问题&#xff0c;享受到高水平的连接体验。本文将为你提供实用的操作…

mysql-事务特性以及隔离机制

一.ACID 事务&#xff08;Transaction&#xff09;是访问和更新数据库的程序执行单元&#xff1b;事务中可能包含一个或多个sql语句&#xff0c;这些语句要么都执行&#xff0c;要么都不执行。 1.逻辑架构和存储引擎 如上图所示&#xff0c;MySQL服务器逻辑架构从上往下可以分…

【C++从0到王者】第二十一站:继承

文章目录 前言一、继承的概念及定义1. 继承的概念2.继承的格式3.继承关系与访问限定符 二、基类和派生类的赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承与友元六、继承与静态成员 前言 继承是面向对象的三大特性之一。我们常常会遇到这样的情况。很多角色的信…

利用OpenCV光流算法实现视频特征点跟踪

光流简介 光流&#xff08;optical flow&#xff09;是运动物体在观察成像平面上的像素运动的瞬时速度。光流法是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系&#xff0c;从而计算出相邻帧之间物体的运动信息的一种方法。…

Kotlin Executors线程池newSingleThreadExecutor单线程

Kotlin Executors线程池newSingleThreadExecutor单线程 import java.util.concurrent.Executorsfun main() {val mExecutorService Executors.newSingleThreadExecutor()for (i in 1..5) {mExecutorService.execute {println("seq-$i tid:${Thread.currentThread().threa…