进程的内存分布

2023-05-16

Linux-内存分布

C进程的内存布局

Linux和windows都是支持多任务多用户的高级操作系统

进程(process):一段程序的执行过程

对于一个C程序,在运行过程中系统对这个进程的内存资源管理非常重要;任何一个程序,想要正常运行都需要内存资源,用来存放诸如变量、常量、函数代码等等。这些不同的内容,所存储的内存区域是不同的,且不同的区域有不同的特性。因此我们需要研究进程的内存布局,逐个了解不同内存区域的特性。

每个C语言进程都拥有一片结构相同的虚拟内存,大小一般为4G,所谓的虚拟内存,就是从实际物理内存映射出来的地址范围,最重要的特征是所有的虚拟内存布局都是相同的,极大地方便操作系统内核管理不同的进程。例如三个完全不相干的进程p1、p2、p3,它们很显然会占据不同区段的物理内存,但经过系统的变换和映射,它们的虚拟内存的布局是完全一样的。

  • PM:Physical Memory,物理内存。

    在这里插入图片描述

  • VM:Virtual Memory,虚拟内存。

在这里插入图片描述

我们平时所谈及程序的内存以及内存地址,指的都是虚拟内存以及虚拟内存地址。将上图中其中一个C语言进程的虚拟内存放大来看,会发现其内部包含以下区域:

在这里插入图片描述

虚拟内存空间又分:

内核空间:1G(0xC000 0000 - 0xFFFF FFFF)

用户空间:3G 包括: 堆、栈 、代码段 、数据段 、不可访问空间:0 ~ 0x0804 8000(128M)

虚拟内存中,内核区段对于用户应用程序而言是禁闭的,它们用于存放操作系统的关键代码,另外由于 Linux 系统的历史性原因,在虚拟内存的最底端 0x00000000 ~ 0x08048000 之间也有一段禁闭的区段,该区段也是不可访问的

定位到用户空间:

虚拟内存中各个区段的详细内容:

在这里插入图片描述

栈内存(statck)

栈内存指的是从0xC000 0000向下增长的这部分区域,具有后进先出的特点。

栈的全称是运行时栈(Run-time Stack),栈会随着进程的运行而不断发生变化:一旦有新的函数被调用,就会立即在栈顶分配一帧内存,专门用来存放该函数内定义的局部变量(形参),当一个函数执行完毕返回之后,它所占用的那帧内存将被释放。

栈还有一个名称叫堆栈,堆栈与堆没有关系。

系统对栈空间大小进行了限制,最大一般为8MB,可以通过以下代码来查看系统对栈空间大小的限制。

cat  /proc/1/limits

什么东西存储在栈内存中?

1.环境变量
2. 命令行参数(传递给你程序)

> 栈中的环境变量和命令行参数在程序开始运行时就被固定在栈底,且进程在整个运行期间不再发生变化;假如进程运行时对环境变量的个数或值做了修改,则为了能够容纳修改后的内容,新的环境变量将会被复制放在**堆**中。

3.局部变量(包括形参)
4.为了可以实现函数的嵌套调用和返回,栈还必须包含函数切换时当下的代码地址和相关寄存器的值,这个过程称为保存现场,等被调用函数执行结束之后,再恢复现场

栈内存有什么特点?(运行时栈)

    • 空间有限,尤其在嵌入式环境下。因此不可以用来存储尺寸太大的变量。
    • 每当一个函数被调用,栈就会向下增长一段,用以存储该函数的局部变量(包括形参)。
    • 每当一个函数退出,栈就会向上缩减一段,将该函数的局部变量所占内存归还给系统。

注意:
栈内存的分配和释放,都是由系统规定的,我们无法干预。

示例代码:
void func(int a, int *p) // 在函数 func 的栈内存中分配
   	{
   	 	double f1, f2;        // 在函数 func 的栈内存中分配
    	...                   // 退出函数 func 时,系统的栈向上缩减,释放内存
	}

	int main(void)
	{
   		int m  = 100;  // 在函数 main 的栈内存中分配
    	func(m, &m);  // 调用func时,系统的栈内存向下增长
	}

堆内存

堆内存(heap)又被称为动态内存、自由内存,简称堆。堆是唯一可被开发者自定义的区段,开发者可以根据需要申请内存的大小、决定使用的时间长短等。但又由于这是一块系统“飞地”,所有的细节均由开发者自己把握,系统不对此做任何干预,给予开发者绝对的“自由”,但也正因如此,对开发者的内存管理提出了很高的要求。对堆内存的合理使用,几乎是软件开发中的一个永恒的话题。

在这里插入图片描述

堆内存基本特征

    • 相比栈内存,堆的总大小仅受限于物理内存,在物 理内存允许的范围内,系统对堆内存的申请不做限制。
    • 相比栈内存,堆内存从下往上增长
    • 堆内存是匿名的,只能由指针来访问。
    • 自定义分配的堆内存,除非开发者主动释放,否则永不释放,直到程序退出。

相关API

    • 申请堆内存:malloc() / calloc() / realloc()
    • 清零堆内存:bzero()
    • 释放堆内存:free()

void *空指针 本身不能直接解引用 必须先转换为其他类型的指针才能使用

在这里插入图片描述

功能:将ptr所指向的堆内存大小扩展为size
原型:void *realloc(void *ptr,size_t size)
返回值:成功:返回扩展后的内存的基地址,可能等于扩展前的地址,也可能不等于。
       失败:返回NULL
备注:当size为0时,该函数相当于free(ptr)
           
           
示例:
int *p = malloc(sizeof(int)); // 申请1块大小为 sizeof(int) 的堆内存
bzero(p, sizeof(int));        // 将刚申请的堆内存清零

*p = 100; // 将整型数据 100 放入堆内存中
free(p);  // 释放堆内存

// 申请3块连续的大小为 sizeof(double) 的堆内存
double *k = calloc(3, sizeof(double));

k[0] = 0.618;
k[1] = 2.718;
k[2] = 3.142;
free(k);  // 释放堆内存    

注意

    • malloc()申请的堆内存,默认情况下是随机值,一般需要用 bzero() 来清零
    • calloc()申请的堆内存,默认情况下是已经清零了的,不需要再清零
    • free()只能释放堆内存,并且只能释放整块堆内存,不能释放别的区段的内存或者释放一部分堆内存。
  • 释放内存的含义:

    • 释放内存意味着将内存的使用权归还给系统
    • 释放内存并不会改变指针的指向
    • 释放内存并不会对内存做任何修改,更不会将内存清零

数据段
在这里插入图片描述
数据段的大小在进程一开始运行就是固定的。
地址从高到低,将数据段分为.bss段、.data段、.rodata段三部分。

  • .bss段专门用来存放未初始化的静态数据(static修饰的局部变量、static修饰的全局变量以及全局变量),它们会在程序刚运行时被系统初始化为0;在程序文件中,它们是没有值的。
  • .data段专门存放已经初始化的静态数据,这个初始值从程序文件中获取
  • .rodata段用来存放只读数据,即常量;比如进程中所有的字符串、字符常量、整型数据、浮点型数据等。

静态数据-static

C语言中,静态数据有三种:

  • 普通全局变量:定义在函数外部的变量。
  • 静态局部变量:定义在函数内部,且被static修饰的变量。
  • 静态全局变量: 定义在函数外部的变量。且被static修饰的变量。
int a; // 全局变量,退出整个程序之前不会释放, 默认被初始化为0,存放在数据段中的 .bss
void f(void)
{
    static int b; // 静态局部变量,退出整个程序之前不会释放,默认被初始化为0,存放在数据段中的.bss
    printf("%d\n", b);
    b++;
}

int main(void)
{
    f();
    f(); // 重复调用函数 f(),会使静态局部变量b的值不断增大
}

为什么需要静态数据?

  1. 全局变量在默认的情况下,对所有文件可见,为某些需要在各个不同文件和函数间访问的数据提供操作上的方便。
  2. 当我们希望一个函数退出后依然能保留局部变量的值,以便于下次调用时还能用时,静态局部变量可帮助实现这样的功能。
  • 注意1:

    • 若定义时未初始化,则系统会将所有的静态数据自动初始化为0
    • 静态数据初始化语句,只会执行一遍
    • 静态数据从程序开始运行时便已存在,直到程序退出时才释放。
  • 注意2:

    • static修饰局部变量:使之由栈内存临时数据,变成了静态数据–生命周期变了作用范围
      不变

    • static修饰全局变量:使之由各文件可见的静态数据,变成了本文件可见的静态数据。

    • static修饰函数:使之由各文件可见的函数,变成了本文件可见的静态函数。

小结:

静态数据指的是存放在数据段的数据–这些数据的生命周期都是程序开始时就存在 ,程序进程结束

才释放被系统回收(static局部变量+static全局变量 +普通全局变量)

代码段

地址从高到低,将代码段分为.text段以及.init段两部分。

  • .text段也叫正文段,用来存放用户程序代码(所有用户自定义函数)。
  • .init段用来存储系统给每一个可执行程序自动添加的初始化代码,这部分代码功能包括:环境变量的准备、命令行参数的组织和传递等,并且这部分数据被存放在栈底。
int a;       // 未初始化的全局变量,放置在.bss 中
int b = 100; // 已初始化的全局变量,放置在.data 中

int main(void)
{
    static int c;       // 未初始化的静态局部变量,放置在.bss 中
    static int d = 200; // 已初始化的静态局部变量,放置在.data 中
    
    // 以上代码中的常量100、200放置在.rodata 中
}

注意:数据段和代码段内存的分配和释放,都是由系统规定的,我们无法干预。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程的内存分布 的相关文章

  • Ubuntu 添加开机/关机执行脚本与service的理解

    最近碰到一个需求是需要在ubuntu中插入一个关机脚本 xff0c 在系统关机之前执行它 在网上浏览了很多资料 xff0c 但是没有切实可行的方法 xff0c 大多数的博客都是比较陈旧的方法 xff0c 可能已经不适用于最新的ubuntu1
  • Linux 进程间通信基础(四)--fifo管道

    最近正好有一些空余时间 xff0c 在这里总结一下曾经使用过的Linux进程间通信的几种方法 xff0c 贴出来帮助有需要的人 xff0c 也有助于自己总结经验加深理解 上一次我们梳理了pipe管道的相关知识 xff0c 这一次梳理fifo
  • 利用二进制文件制作自己的Debian软件安装包

    在使用Ubuntu系统的时候 xff0c 我们已经习惯了使用Debian风格的软件安装方式 即使用apt get install命令安转或dpkg i deb的方式安装debena软件包 但有时程序没有放到Ubuntu的源服务器上且不提供d
  • Tortoise Git 克隆出现"fatal: Authentication failed for"

    使用Tortoise Git克隆时出现 34 fatal Authentication failed for 34 的错误 xff0c 并且他还不让你输入用户名和密码 xff0c 寻找了许多办法 xff0c 看到最多的是在Git Bash中
  • 怎么解决 接口请求 504 Gateway Time-out

    HTTP 504 Gateway Timeout 错误通常是由于网关或代理服务器无法在规定的时间内从上游服务器接收到响应而导致的 这可能是由于上游服务器过载或网络问题导致的 要解决此问题 xff0c 可以尝试以下步骤 xff1a 检查上游服
  • WSL无法使用npm

    报错信息 root 64 DESKTOP U2RC2DU npm bash mnt c Program Files nodejs npm bin sh M bad interpreter No such file or directory
  • HDU 3700 Line belt

    Line belt Time Limit 2000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 3669 Accepted Su
  • Ubuntu中使用framebuffer的方法

    打开 etc initramfs tools modules文件 xff0c 在末尾加上 xff1a fbcon vesafb 打开 etc modprobe d blacklist framebuffer xff0c 找到 blackli
  • html5.超链接标签,图片标签

    lt a gt 超链接标签 a标签常用的属性 xff1a href 用于指定链接的资源 target 设置打开新资源的目标 Blank 在独立的窗口上打开新资源 self 在当前窗口打开新资源 file file协议 xff08 文件协议
  • ubuntu22.04 搭建 Pytorch环境

    关于电脑 第一步 安装anaconda 1 进入官网 链接 anaconda 2 下载linux的sh版 3 在对应位置输入 span class token function sh span 文件名 sh 4 选择 yes 5 选择no
  • opencv的ORB特征(slambook2 orb_cv.cpp代码详解)

    ORB特征提取与匹配 slambook2 ch7 orb cv cpp 1 头文件 span class token macro property span class token directive hash span span clas
  • Debian安装nodejs

    安装指定版本nodejs xff0c 以18 X版本为例 1 通过curl命令向系统中添加NodeSource存储库 curl sL https deb nodesource com setup 18 x bash xff08 如果提示 c
  • pip安装第三方库全攻略:普通安装、安装whl后缀文件、使用国内镜像安装

    简介 xff1a pip 是 Python 的包安装程序 其实 xff0c pip 就是 Python 标准库 xff08 The Python Standard Library xff09 中的一个包 xff0c 只是这个包比较特殊 xf
  • Python:处理cv2模块putText中文无法识别问题

    简介 xff1a 在cv2中 xff0c 目前putText函数中文是无法直接使用的 xff0c 需要进行一点的转换 解决办法为通过PIL模块重新封装一个函数 xff0c 直接调用 如图 xff1a 通过PIL模块改造 xff1a new
  • VLC播放电视直播rtmp流地址

    简介 xff1a RTMP是Real Time Messaging Protocol xff08 实时消息传输协议 xff09 的首字母缩写 该协议基于TCP xff0c 是一个协议族 xff0c 包括RTMP基本协议及RTMPT RTMP
  • Python:global的使用

    简介 xff1a 1 global是Python中的全局变量关键字 2 全局变量是编程术语中的一种 xff0c 源自于变量之分 3 变量分为局部与全局 xff0c 局部变量又可称之为内部变量 4 由某对象或某个函数所创建的变量通常都是局部变
  • Python:opencv画点、圆、线、多边形、矩形

    简介 xff1a 机器学习视觉方向一般都需要在图像中添加标注框 xff0c 标注框有着很大的用处 xff0c 特别是对图像中某些需要关注的特征起到圈定的效果 xff0c 方便对特征选择进行处理 相关攻略 xff1a 机器学习 xff1a 基
  • adb重启或关机手机命令

    简介 xff1a 在某些特殊场景中 xff0c 例如手机真机不在身边 xff0c 但已通过adb进行连接 xff0c 可以使用命令进行远程关机或者重启 相关攻略 xff1a adb xff1a 常用命令 adb xff1a win10系统下
  • docker:更换镜像源

    简介 xff1a 因为国内的网络访问问题 xff0c 为加快拉取镜像速度 xff0c 建议设置docker国内镜像源 相关攻略 xff1a win10 xff1a 安装docker和测试安装redis centos7 6 xff1a 安装d

随机推荐

  • 七大顶级Linux桌面比较

    1七大顶级Linux桌面 xff1a Unity 对于开源Linux平台来说 xff0c 如何选择就是首要解决的问题 通常Linux发行版都有默认的桌面成为你的首选 xff0c 但目前可供选择的桌面环境种类繁多 特别是Ubuntu系统一个平
  • Linux:安装go环境

    简介 xff1a Go xff08 又称 Golang xff09 是 Google 的 Robert Griesemer xff0c Rob Pike 及 Ken Thompson 开发的一种静态强类型 编译型语言 Go 语言语法与 C
  • docker应用:搭建私有云盘

    简介 xff1a NextCloud是一个开源的云存储解决方案 xff0c 可以在自己的服务器上搭建个人云存储系统 它提供了与市面上主流云存储服务 xff08 如Dropbox Google Drive xff09 相似的功能 xff0c
  • Flask+A-Frame:交互式全景图展示网站

    简介 xff1a 通过结合 Flask 轻量级 Web 框架与 A Frame 3D 和 VR 技术 xff0c 实现了一个可交互的全景图展示功能 xff0c 用户可以在浏览器中自由观看 旋转和缩放全景图片 项目的核心是使用 Flask 搭
  • OpenCV合成全景图

    简介 xff1a OpenCV 利用特征提取 特征匹配 齐次估计 图像配准和图像融合等技术 xff0c 将一系列图像合成为全景图 OpenCV 和 Pillow 是两个功能强大的 Python 图像处理库 xff0c 但它们在处理全景图拼接
  • BDD行为驱动开发+Python案例解析

    简介 xff1a BDD xff08 Behavior Driven Development xff0c 行为驱动开发 xff09 是一种敏捷软件开发方法 xff0c 它强调软件应该按照预期的行为来开发 BDD的核心理念是使用自然语言编写的
  • 操作系统迭代、Debian安装教程

    前言 最近在考虑公司生产环境操作系统的迭代问题 目前 xff0c 公司业务主要跑在CentOS7和8上面 xff0c 由于CentOS早已停止了7和8的支持 xff0c 新版的CentOS Stream也从RHEL的下游变成了上游 xff0
  • Debian修改DNS

    原文链接 Debian的DNS文件默认为 etc resolv conf 查看当前的DNS cat etc resolv conf 下图中画出的就是当前系统的DNS 如果想修改DNS的话 xff0c 可以直接vim 来修改文件 xff0c
  • 配置JupyterLab远程密码访问

    文章目录 部署环境配置步骤启动和连接访问启动连接访问 有些时候因为某些原因 xff08 如本地机器资源不足 数据不能离网等 xff09 xff0c 需要使用本地电脑连接远程服务器进行开发工作 xff0c 在这里记录下如何在远程Linux上配
  • linux查看 jre 安装目录

    近期对接平安银行项目 xff0c 要求放国密 jar包到jre目录 xff0c 网上也找了一些命令 xff0c 下面这个亲测有用 xff0c 特此记录一下 xff0c 我的系统版本是3 10 0 693 el7 x86 64 步骤 1 使用
  • Python选择网卡发包及接收数据包

    当一台计算机上有多个网卡时 xff0c 需要选择对应IP地址的网卡进行发送数据包或者接受数据包 1 选择网卡发包 xff08 应用scapy xff09 xff1a plface 61 conf route route 34 34 0 为对
  • php 使用 Excel/reader.php, 导入excel到数据库 ,解决The file is not readable。。

    今天小伙伴上传excel到服务器 并导入到数据库中 xff0c 可是文件一直出现 The file is not readable 是哪里的代码抛出的异常呢 xff1f 是Spreadsheet Excel Reader类里面 其中抛出异常
  • “The Language Support for Java server crashed“ 问题解决方案

    The Language Support for Java server crashed 问题解决方案 环境 xff1a Windowsvs code 1 356 14日最新发布的VSCodeJavaInstaller online win
  • (循环读取网易云缓存文件转mp3)

    循环读取网易云缓存文件转mp3 import java io DataInputStream import java io DataOutputStream import java io File import java io FileIn
  • 洛谷P4180 [BJWC2010]严格次小生成树

    传送门 之前写过一次 xff0c 但是理解不深刻 xff0c 复习之后有了更加细节的一些理解 好了进入正题 首先 xff0c 我们需要知道次小生成树一定是在最小生成树的邻集中 xff0c 即次小生成树与最小生成树只会有一条边的差别 所以我们
  • MarkDown学习笔记

    MarkDown学习笔记 目录 MarkDown学习笔记 1 标题2 段落3 文字3 1斜体3 2加粗3 3斜体 43 加粗3 4删除线3 5下划线3 6字体背景 4 分隔线5 扩展语法的说明6 高亮 xff08 需要勾选扩展语法 xff0
  • 格式化标准输出函数printf()与格式化标准输入函数scanf()

    printf 函数与scanf 函数 文章目录 printf 函数与scanf 函数格式化标准输出函数 printf 相关函数 xff1a 返回值参数执行顺序打印较长字符串格式控制符 xff1a 输出缓冲区printf 的标志转义字符类型修
  • 数据在内存中的存储

    数据在内存中的存储 文章目录 数据在内存中的存储计算机中的数据数据类型类型的基本归类整型在内存中的存储原码 反码 补码大小端介绍浮点型在内存中的存储二进制与十进制的转换 计算机要处理的信息是多种多样的 xff0c 如数字 文字 符号 图形
  • 特殊函数--变参函数及相关宏

    特殊函数 变参函数 定义的函数在使用时传入的参数是不定量不定类型 变参函数 include lt stdarg h gt 例子 xff1a printf 34 abc d def c g n 34 num ch xff09 其中 34 ab
  • 进程的内存分布

    Linux 内存分布 C进程的内存布局 Linux和windows都是支持多任务多用户的高级操作系统 进程 xff08 process xff09 xff1a 一段程序的执行过程 对于一个C程序 xff0c 在运行过程中系统对这个进程的内存