大话C语言:第27篇 内存模型

1 存储硬件概述

现代计算机遵循冯诺依曼体系结果,存储分为:

  • 外部存储器:长期存放数据,掉电不丢失数据。例如,硬盘、flash、rom、u 盘、光盘、磁带。

  • 内部存储器:暂时存放数据,掉电数据丢失。例如,DDR内存条

应用程序从外部存储器加载至内部存储器过程包括:

  • 用户启动应用程序:用户通过点击图标、从命令行运行或其他方式启动应用程序。

  • 操作系统响应:操作系统接收到启动请求,并开始处理;如果应用程序尚未在内存中,操作系统会查找应用程序在磁盘上的位置(通常是可执行文件)。

  • 加载程序(Loader)工作:加载程序首先读取应用程序的头部信息,这通常包括程序所需的各种资源、依赖项和代码段的位置。

  • 读取代码和数据:加载程序从磁盘读取应用程序的代码段、数据段和其他必要的段。这些段通常包括程序的指令(即代码)和程序运行所需的数据。

  • 分配内存空间:操作系统为应用程序分配所需的内存空间。这通常涉及到管理物理内存和虚拟内存。

  • 加载至内存:将从磁盘读取的代码和数据段加载到分配的内存空间中。如果内存空间不足以容纳整个应用程序,操作系统会使用虚拟内存技术,将部分应用程序存储在磁盘上,并在需要时将其交换到RAM中。

  • 设置程序计数器和其他寄存器:操作系统设置程序计数器(PC)以指向程序的入口点(即程序开始执行的指令)。还会设置其他必要的寄存器,以支持程序的执行。

  • 执行:一旦程序在内存中准备好,操作系统会将控制权交给应用程序,程序开始执行。

2 物理内存和虚拟内存

  • 物理内存:实实在在存在的存储设备

  • 虚拟内存:内存管理的一种技术,它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间)。

其中,虚拟内存的工作原理是将进程使用的内存分为多个页面(通常为4KB或8KB),每个页面都有一个唯一的虚拟地址。当进程需要访问某个页面时,操作系统会检查该页面是否已经在物理内存中。如果已经在内存中,则直接访问该页面;如果不在内存中,则操作系统会将该页面从磁盘上的虚拟内存中读取到内存中,并将其映射到进程的虚拟地址空间中。

操作系统会在物理内存和虚拟内存之间做映射。

其中,虚拟内存主要有以下几种类型:

  • 分页式虚拟存储:物理内存和虚拟内存都被划分为固定大小的页面(Page)。当程序需要更多内存时,操作系统将不常用的页面移动到硬盘上的交换空间,并将需要的页面加载到物理内存中。这种方式实现了内存的动态分配和页面的调度,但需要频繁地进行页面调入和调出,可能影响系统性能。

  • 段式虚拟存储:程序的地址空间被划分为多个逻辑段,每个段可以具有不同的长度和访问权限。当程序需要内存时,操作系统将程序的逻辑段映射到物理内存或硬盘上的交换空间。这种方式更灵活,可以根据程序的需要分配不同大小的内存空间,但需要额外的管理和调度。

  • 请求分页式虚拟存储:结合了分页式和段式虚拟存储的特点。在这种方式中,程序的地址空间被划分为多个段,每个段又被划分为多个页面。

3 逻辑地址和物理地址

  • 逻辑地址:是指程序在运行过程中使用的地址,也称为虚拟地址(Virtual Address)。它是由CPU生成的,用于访问内存中的数据。逻辑地址的大小和位数取决于处理器的架构和操作系统的设计,通常是一个定长的二进制数值。在执行指令时,CPU通过将逻辑地址转化为物理地址来获取数据。

  • 物理地址:是指内存中实际的地址,也称为实地址(Real Address)。物理地址表示内存模块中每个存储单元(通常是字节)的唯一标识符,因此具有唯一性,且直接与内存相关联。物理地址通常是一个以十六进制表示的数字,它确定了计算机中的实际内存位置。

其中,应用程序主要使用的是逻辑地址;逻辑地址是程序代码中使用的地址,由程序员或操作系统生成。在 32 位系统下,每个进程(运行着的程序)的寻址范围是 0x00000000 ~0xff ff ff ff,空间大小为4G。

4 C语言程序内存布局

4.1 系统空间

存放在整个内核的代码和所有的内核模块,用来内核空间执行 Linux 系统调用。

4.2 栈区

存局部变量、函数,调用函数时会开辟栈区,函数结束时就自动回收,遵循后进先出的原则,从高地址向低地址增长。

栈区主要特点包括:

  • 栈内存由编译器在程序编译阶段完成。

  • 函数返回后该函数的栈空间消失,所以函数中返回局部变量的地址都是非法的。

  • 栈区存放局部变量。

  • 堆区的空间是由下往上增长的。

  • 自动分配内存,{}内有效,离开{}自动释放。

  • 未初始化的值为随机值。

  • 未初始化的静态局部变量,其值为0

4.3 堆区

malloc、realloc、calloc等开辟的内存就在堆,从低地址向高地址增长,由程序员分配和释放,系统不自动回收,所以一定要记得申请了就要释放,以免溢出。动态内存是开发者手动分配的,是堆分配的。

堆的主要特点:

  • 堆内存是在程序执行过程中分配的,用于存放进程运行中被动态分配的的变量。

  • 函数返回这段内存不会消失。

  • 动态申请的内存,程序员自己管理,用完要free,否则内存泄漏。

  • 堆区的空间是由下往上增长的。

  • 内存里面的内容为随机值,一般用memset函数清0。

注意,

  • 避免分配大量的小内存块。分配堆上的内存有一些系统开销,所以分配许多小的内存块比分配几个大内存块的 系统开销大。

  • 仅在需要时分配内存。只要使用完堆上的内存块,就需要及时释放它(如果使用动态分配内存,需要遵守原则: 谁分配,谁释放), 否则可能出现内存泄漏

4.4 数据段

数据段包含程序中已经初始化的全局变量和静态变量。这些变量在程序运行期间一直存在,并且它们的值在程序开始执行之前就已经确定。

数据段可以进一步细分为已初始化数据段(包含有明确初始值的全局变量和静态变量)和未初始化数据段(也称为BSS段,包含未明确初始化的全局变量和静态变量,通常初始化为0)。

数据段分为:

  • rodata段:Read-Only Data段的缩写,是程序内存中的一个特定区域,用于存放只读数据,也就是那些不可修改的常量数据。这些数据在程序执行期间不会发生变化,因此被设计为只读,以防止程序意外地修改它们。rodata段常被称为常量区,存放的是诸如整数常量、字符串常量等。

  • bss段:程序内存布局中的一个特定段,它主要用于存放程序中未初始化的全局变量和静态变量。这些变量在编译时并没有明确赋予初值,因此在程序加载到内存时,系统会自动将bss段的内存空间清零,以保证这些变量在使用前具备确定的初值。

  • data段:主要用于存储程序中已经初始化且初值不为0的全局变量和静态局部变量。这些数据在程序编译时就已经确定,并且在程序运行期间会保持不变,因此它们被存放在一个可读可写的内存区域中。

注意,data段与bss段在功能上有所区别:

  • bss段主要用于存储未初始化的全局变量和静态变量,这些变量在程序加载时会被自动初始化为0。而data段则专门用于存储已初始化的非零变量。这种分工使得内存管理更为高效和有序。

  • 在程序执行过程中,data段的内容是保持不变的。这是因为这些数据在程序编译时已经确定,并且在程序运行期间不会被修改。这使得.data段成为程序中的一个稳定的数据存储区域,为程序提供了可靠的数据支持。

4.5 文本段

文本段,也称为代码段或简称为文本,是目标文件或内存中的程序段之一,其中包含可执行指令。作为内存区域,可以将文本段放置在堆或堆栈下方,以防止堆和堆栈溢出覆盖它。

通常,文本段是可共享的,因此对于频繁执行的程序(例如文本编辑器、C 编译器、shell 等),只需要在内存中保存一个副本。此外,文本段通常是只读的,以防止程序意外修改其指令。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小白学python(第六天)循环之异变

本篇文章给大家讲解的是循环语句,那么闲话少叙,我们进入正题 在c、Java中循环都是三剑客,那么大家可还记得是哪三位剑客吗 剑客一:while循环 剑客二:for循环 剑客三:do{……}while(&…

springcloud-alibba之FeignClient

代码地址&#xff1a;springcloud系列: springcloud 组件分析拆解 1.FeignClient的集成 springboot版本&#xff1a;3.1.5 springcloud组件版本&#xff1a;2022.0.4 nacos客户端的版本&#xff1a;2.3.2 1.引pom 这里引入了nacos和feginclient的版本 <dependency>…

MongoDB 单节点升级为副本集高可用集群(1主1从1仲裁)

作者介绍&#xff1a;老苏&#xff0c;10余年DBA工作运维经验&#xff0c;擅长Oracle、MySQL、PG、Mongodb数据库运维&#xff08;如安装迁移&#xff0c;性能优化、故障应急处理等&#xff09; 公众号&#xff1a;老苏畅谈运维 欢迎关注本人公众号&#xff0c;更多精彩与您分享…

SpringBoot 实现视频分段播放(通过进度条来加载视频)

需求&#xff1a;现在我本地电脑中有一个文件夹&#xff0c;文件夹中都是视频&#xff0c;需要实现视频播放的功能。 问题&#xff1a;如果通过类似 SpringBoot static 文件夹的方式来实现&#xff0c;客户端要下载好完整的视频之后才可以播放&#xff0c;并且服务端也会占用大…

计算机网络之以太网

上文内容&#xff1a;总线局域网以及冲突的解决方法 1.以太网的起源 1.1起源 60年代末期&#xff0c;夏威夷大学Norman Abramson等研制ALOHA无线网络系统,实现Oahu岛上的主机和其它岛及船上的读卡机和终端通信&#xff1b; 出境信道地址&#xff1a;主机到终端&#xff1…

vue3 + 百度地图 实现多坐标生成轨迹的两种种方式

本次依然是关于百度地图中常见的一个问题&#xff0c;此次共使用了两种方式并做了一些分析及处理&#xff0c;希望有所帮助。如有问题可以评论或私信。 一、便捷方式 优点&#xff1a;便捷&#xff0c;所用的api方法是根据坐标进行计算后绘制路线&#xff0c;所以路线相对准确…

制定事件响应计划的四个关键步骤,如何做到风险闭环

一个有效的安全事件响应策略的关键组成部分有哪些&#xff1f;一个有效的安全事件响应策略包括四个关键组成部分&#xff0c;它们协同工作以确保对网络安全问题的快速和有效响应。 一个有效的安全事件响应策略的关键组成部分有哪些&#xff1f; 一个有效的安全事件响应策略包括…

Java常用算法集合扩容机制分析

基础篇 基础篇要点&#xff1a;算法、数据结构、基础设计模式 1. 二分查找 要求 能够用自己语言描述二分查找算法能够手写二分查找代码能够解答一些变化后的考法 算法描述 前提&#xff1a;有已排序数组 A&#xff08;假设已经做好&#xff09; 定义左边界 L、右边界 R&…

SQLite 命令行客户端 + Windows 批处理应用

SQLite 命令行客户端 Windows 批处理应用 下载 SQLite 客户端1. Bat 辅助脚本1. 执行SQL.bat执行 2. 导出Excel.bat执行效果 3. 导出HTML.bat执行效果 4. 清空-订单表.bat 2. 测试 SQL1. 创建订单表.sql2. 插入订单表.sql3. 查询订单表.sql4. 清空订单表.sql5. 删除订单表.sql…

linux驱动编程 - kfifo先进先出队列

简介&#xff1a; kfifo是Linux Kernel里面的一个 FIFO&#xff08;先进先出&#xff09;数据结构&#xff0c;它采用环形循环队列的数据结构来实现&#xff0c;提供一个无边界的字节流服务&#xff0c;并且使用并行无锁编程技术&#xff0c;即当它用于只有一个入队线程和一个出…

黑马的ES课程中的不足

在我自己做项目使用ES的时候&#xff0c;发现了黑马没教的方法&#xff0c;以及一些它项目的小问题 搜索时的匹配方法 这个boolQuery().should 我的项目是通过文章的标题title和内容content来进行搜索 但是黑马它的项目只用了must 如果我们的title和content都用must&#x…

Arc for Windows 无法使用?一篇文章教会你!

&#x1f44b; 大家好&#xff0c;我是 Beast Cheng &#x1f4eb; 联系我&#xff1a;458290771qq.com &#x1f331; 接合作、推广…… 什么是Arc浏览器&#xff1f; Arc浏览器是The Browser Conpany使用Swift语言开发的一款浏览器&#xff0c;Arc浏览器由其漂亮的侧边栏闻名…

HTML5使用<mark>标签:高亮显示文本

1、<mark>标签的使用 mark 标签用于表示页面中需要突出显示或高亮的一段文本&#xff0c;这段文本对于当前用户具有参考作用。它通常在引用原文以引起读者注意时使用。<mark>标签的作用相当于使用一支荧光笔在打印的纸张上标出一些文字。它与强调不同&#xff0c;…

自闭症在生活中的典型表现

自闭症&#xff0c;这个看似遥远却又悄然存在于我们周围的疾病&#xff0c;其影响深远且复杂。在日常生活中&#xff0c;自闭症患者的典型表现往往让人印象深刻&#xff0c;这些表现不仅揭示了他们内心的世界&#xff0c;也提醒我们要以更加包容和理解的心态去面对他们。 首先…

UEC++ 虚幻5第三人称射击游戏(二)

UEC++ 虚幻5第三人称射击游戏(二) 派生榴弹类武器 新建一个继承自Weapon的子类作为派生榴弹类武器 将Weapon类中的Fire函数添加virtual关键字变为虚函数让榴弹类继承重写 在ProjectileWeapon中重写Fire函数,新建生成投射物的模版变量 Fire函数重写逻辑 代码//生成的投射物U…

MySQL中mycat与mha应用

目录 一.Mycat代理服务器 1.Mycat应用场景 2.mycat安装目录结构说明 3.Mycat的常用配置文件 4.Mycat日志 5.mycat 实现读写分离 二.MySQL高可用 1.原理过程 2.MHA软件 3.实现MHA 一.Mycat代理服务器 1.Mycat应用场景 Mycat适用的场景很丰富&#xff0c;以下是几个典型…

大模型的实践应用25-LLama3模型模型的架构原理,以及手把手教你搭建LLama3模型

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用25-LLama3模型模型的架构原理,以及手把手教你搭建LLama3模型。LLaMA 3 是Meta公司开发的最新一代大规模语言模型,其架构在很大程度上继承了LLaMA 2的设计,但对某些关键组件进行了改进和优化。 文章目录 一、LLama3模…

Vue通过Key管理状态

Vue通过Key管理状态 Vue 默认按照“就地更新”的策略来更新&#xff0c;通过 v-for 渲染的元素列表。当数据项的顺序改变时&#xff0c;Vue 不会随之移动 DOM 元素的顺序&#xff0c;而是就地更新每个元素&#xff0c;确保它们在原本指定的索引位置上渲染。为了给 Vue 一个提示…

mupdf加载PDF显示中文乱码

现象 加载PDF显示乱码,提示非嵌入字体 non-embedded font using identity encoding调式 在pdf-font.c中加载字体 调试源码发现pdf文档的字体名字居然是GBK&#xff0c;估计又是哪个windows下写的pdf生成工具生成pdf 字体方法&#xff1a; static pdf_font_desc * load_cid…