【Linux】深入理解程序地址空间
🌟🌟作者主页:ephemerals__
🌟🌟所属专栏:Linux
目录
前言
一、什么是程序地址空间
二、深入理解程序地址空间
1. 引例
2. 理解地址转化
3. 再谈程序地址空间
4. 补充知识
总结
前言
在现代操作系统中,进程的地址空间管理是实现多任务和内存保护的核心机制。对于Linux操作系统而言,理解程序的地址空间布局不仅对于开发高效、稳定的应用至关重要,也是调试和优化程序不可或缺的基础。本文将简要介绍Linux程序在内存中的地址空间结构,帮助读者更好地理解进程如何利用和管理内存资源。
一、什么是程序地址空间
程序地址空间是指操作系统为一个程序分配的内存范围。在现代操作系统中,每个程序在运行时都有自己的程序地址空间。
程序地址空间通常分为以下几个部分:
1. 内核空间:供操作系统使用,与其他部分形成隔离,程序无法访问。
2. 栈区:存储函数的局部变量和函数调用的上下文等。
3. 内存映射段(共享区):为支持文件的高效访问或多进程的数据共享而划分的一块区域,通常包含文件映射、动态库和匿名映射等。
4. 堆区:动态内存分配所用区域,需要手动管理。
5. BSS段:存储未初始化的全局变量和静态变量。
6. 数据段(静态区):存储已经初始化的全局变量和静态变量。
7. 代码段(常量区):存放程序的可执行代码和只读常量,该区域通常只读,不可修改。
在32位系统下,程序地址空间一共有2^32个地址,大小为4GB;
在64位系统下,程序地址空间一共有2^64个地址,大小约为17179PB(是理论极限,实际比它小得多,并且整个内存大小远远达不到如此) 。
二、深入理解程序地址空间
1. 引例
首先我们写一段程序:
#include <stdio.h>
#include <unistd.h>int main()
{int m = 0;pid_t id = fork();if(id == 0) // 子进程{m = 10;printf("子进程修改了m\n");sleep(1);printf("子进程:m = %d;&m = %p\n", m, &m);}else // 父进程{sleep(1);printf("父进程:m = %d;&m = %p\n", m, &m);}return 0;
}
这里我们使用fork创建了一个子进程,并让子进程修改m的值,此时会发生写时拷贝,两个进程的“m”应该不再表示同一份资源。接下来打印它们的值和地址。程序运行结果如下:
可以看到,出现了怪事:m的值不同,为什么它们的地址还相同呢?
只能说明:这个地址是假的,不是真实的内存地址(物理地址)。
实际上,我们使用C/C++编程时使用到的地址,全部都是虚拟地址,并不表示真实的内存地址。为了保护物理内存,真实的内存地址是由操作系统统一管理的,用户无法直接访问。
2. 理解地址转化
因此,刚才的例子当中,两个m的虚拟地址是相同的,但在物理层面,它们的物理地址是不同的。这就意味着两个进程的虚拟地址空间是不同的,并且操作系统必须将用户使用的虚拟地址转化为物理地址,然后进行访问等操作。负责虚拟地址和物理地址转化的东西,叫做页表。
我们可以暂时将页表理解为一个映射表,表的左边是虚拟地址,右边是物理地址,通过左边的虚拟地址就可以进行页表转化,找到真实的物理地址进行访问。
总结:
1. 一个进程具有一个程序地址空间
2. 一个进程具有一个页表,用于虚拟地址和物理地址的转化
3. 程序执行时,操作系统根据数据或代码的虚拟地址,通过页表找出对应的真实内存地址,进行访问。
3. 再谈程序地址空间
因此,再说“程序地址空间”就不太准确了,我们称其为“进程地址空间”或“虚拟地址空间”更为恰当。
实际上,不仅进程地址空间的地址是虚拟的,其“大小”也是虚拟的。进程地址空间就像是操作系统给进程画的一张大饼,让进程以为自己独占4GB的内存(32位系统下)。但由于其他进程可需要访问物理内存,物理内存总共就4GB,怎么可能被一个进程独占呢?所以虽说进程地址空间大小是4GB,但实际根本不可能有这么多。
因此,进程在创建时,操作系统按照程序代码和数据的大小,创建地址空间,并设定各个区域的范围和内存大小,然后加载程序,申请相应的物理内存,再创建页表,支持将物理地址转化为虚拟地址,供上层用户使用。
这样,我们就可以解释刚才的程序:
1. 子进程在创建之后,拷贝了父进程的进程地址空间以及页表,因此,父子进程的地址映射关系是相同的,具体表现就是虚拟地址相同,且维护的是同一块物理内存。
2. 此时子进程修改变量m的值,操作系统检测到变量要被修改,于时发生写时拷贝,在物理内存中对该变量进行拷贝,并修改子进程的页表映射关系,使原来的虚拟地址映射到别的物理地址处。这样,父子进程就各自维护一个m,它们表现出的虚拟地址相同,但物理地址不同,页表映射关系也不同,因此出现了地址相同,值不相同的情况。
那么为什么不支持直接访问物理内存,而这样大费周折地搞出一个什么进程地址空间和页表呢?有三点原因:
1. 如果每个进程都可以直接访问物理内存,那么就意味着这个程序可以直接修改另一个程序甚至操作系统的数据和代码,如果有恶意病毒程序,就会造成不可预料的后果。
2. 假设进程A需要申请地址为1~100的内存区域,并且代码中访问了地址为“50”的内存单元。下一次启动进程A时,如果已经有进程申请了1~100的内存区域,那么进程A如何申请内存呢?尚且申请101~200,但是代码中访问“50”已经写死了,没法修改,这导致每次程序执行的结果都是不确定的。
3. 如果直接使用物理内存,那么一个进程就是一整块内存区域,如果需要执行挂起或其他操作,就只能将整个区域都进行拷贝,效率降低。
进程地址空间的出现,就完美地解决了这些问题:
1. 地址转换过程中,可以对操作的合法性进行判定(页表中,针对虚拟地址空间中的各个区域,有明确的权限划分,假如在程序中修改常量数据,就会出现页表权限拦截,发生崩溃),从而保护物理内存,确保程序的正常执行。
2. 有了虚拟地址,物理内存申请就不必连续,经过页表可以转化成连续的虚拟地址,方便上层使用。
3. 除此之外,程序地址空间还使得操作系统对进程的管理和内存的管理之间进行一定的解耦合(用户申请内存根本无需关心物理内存的具体情况)。
4. 补充知识
1. 虚拟地址空间的本质是一个数据结构,在Linux下叫做mm_struct,其地址存放在task_struct对象当中,mm_struct维护着一个个vm_area_struct,这些vm_area_struct存储着进程地址空间每一个区域的起始和结束地址。要调整区域划分,只需对其中变量进行加减操作。
2. 一个进程具有一个进程地址空间,意味着一个进程维护一个mm_struct,操作系统要将这些mm_struct组织起来统一管理。当进程数量较少时,mm_struct是用单链表结构组织起来的;较多时,利用红黑树结构进行组织。
总结
本篇文章,我们学习了进程地址空间的基本概念,并深入理解了页表转化以及进程地址空间的本质。学习进程地址空间,为我们后续学习理解进程控制相关操作至关重要。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤
相关文章:
【Linux】深入理解程序地址空间
🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、什么是程序地址空间 二、深入理解程序地址空间 1. 引例 2. 理解地址转化 3. 再谈程序地址空间 4. 补充知识 总结 前言 在现代操作系…...
基于AWS Marketplace的快速解决方案:从选型到部署实战
1. 引言:为什么选择AWS Marketplace? 在数字化转型的背景下,企业需要快速获取成熟的软件工具和服务以降低开发成本。AWS Marketplace 作为亚马逊云科技的官方应用商店,提供超过万款预配置的第三方和AWS原生解决方案,涵…...
Android 常用输入控件
一 控件名称 TextView二 示例代码 <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.a…...
ubuntu修改时区和设置24小时格式时间
这里写目录标题 一、修改时区二、设置24小时格式时间endl 一、修改时区 使用timedatectl命令更改当前时区为东八区[rootubuntu24-16:~]# timedatectl list-timezones | grep -i shanghai Asia/Shanghai [rootubuntu24-16:~]# timedatectl set-timezone Asia/Shanghai [rootubu…...
Android之Button、ImageButton、ChipGroup用法
一 控件名称及UI代码 Button、ImageButton、ChipGroup <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app=&qu…...
【中间件】brpc_基础_用户态线程中断
bthread之用户态线程中断 源码 1 简介 interrupt_pthread 核心功能是 通过信号机制中断阻塞的 pthread 线程,以实现线程的协作式中断。 2 核心功能与设计 2.1 信号选择与注册 信号选择:使用 SIGURG 作为中断信号。 原因:SIGURG 通常用于…...
MATLAB中tabulate函数——先验概率的简单估计
load fisheriris X meas(:,1:2); Y species; labels unique(Y); tabulate(Y)ValueCountPercentsetosa5033.33%versicolor5033.33%virginica5033.33%...
修复笔记:SkyReels-V2 项目中的 torch.load 警告
#工作记录 一、问题描述 在运行项目时,出现以下警告: FutureWarning: You are using torch.load with weights_onlyFalse (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pic…...
[特殊字符] 人工智能大模型之开源大语言模型汇总(国内外开源项目模型汇总) [特殊字符]
Large Language Model (LLM) 即大规模语言模型,是一种基于深度学习的自然语言处理模型,它能够学习到自然语言的语法和语义,从而可以生成人类可读的文本。 所谓 "语言模型",就是只用来处理语言文字(或者符号…...
自监督学习(Self-supervised Learning)李宏毅
目录 Self-supervised Learning简介: BERT : How to use BERT case1:sequence to class 语言积极性OR消极性判断 case2:sequence to sequence句子中的词语词性标注 case3:sequence2 to class两个句子是不是一个为前提一个为…...
数字化时代下,软件测试中的渗透测试是如何保障安全的?
在如今数字化与信息化的时代,软件测试中存在渗透测试,其位置十分重要,它借助模拟恶意攻击的方式,去发现软件系统所存在的漏洞以及安全问题,这是保障软件安全的关键环节,接下来我会对它的各个方面进行详细介…...
内容中台的AI中枢是什么?
智能算法与知识图谱融合引擎 现代内容中台的核心竞争力在于智能算法与知识图谱的深度融合,这种技术组合构建了动态演化的认知网络。通过将机器学习模型与领域知识图谱进行耦合,系统不仅能识别文本、图像、视频等多模态数据的关联特征,还能实…...
PostgreSQL 的 REINDEX 命令
PostgreSQL 的 REINDEX 命令 REINDEX 是 PostgreSQL 中用于重建索引的重要命令,它可以解决索引损坏、索引膨胀或性能下降等问题。 一 REINDEX 基本语法 -- 重建单个索引 REINDEX [ ( option [, ...] ) ] { INDEX | TABLE | SCHEMA } [ CONCURRENTLY ] name REIND…...
GNOME扩展:Bing壁纸
难点 网络请求(Soup) 下载文件(Soup) 读写设置(Gio.Settings) 源码 import GLib from "gi://GLib"; import Gio from gi://Gio; import St from gi://St; import Soup from gi://Soup;import { Extension } from resource:///org/gnome/shell/extensions/extens…...
BUUCTF——Fake XML cookbook
BUUCTF——Fake XML cookbook 进入靶场 只有一个登录框 先弱口令万能密码试一下吧 弱口令和万能密码都失败了 找其他突破口 F12看看 发现xml代码 function doLogin(){var username $("#username").val();var password $("#password").val();if(user…...
【数据结构】线性表--链表
【数据结构】线性表--链表 一.前情回顾二.链表的概念三.链表的实现1.链表结点的结构:2.申请新结点函数:3.尾插函数:4.头插函数:5.尾删函数:6.头删函数:7.在指定结点之前插入:8.在指定结点之后插…...
2022年第十三届蓝桥杯省赛B组Java题解
2022年第十三届蓝桥杯省赛B组Java题解 个人心得: 2022年蓝桥杯省赛Java B组共包含10道题目,其中填空题2道(A、B),编程题8道(C-J)。题目覆盖数论、字符串处理、动态规划、数据结构等核心知识点…...
【操作系统】死锁
1. 定义 死锁是指两个或多个进程(或线程)在执行过程中,因争夺资源而造成的一种僵局,每个进程都无限期地等待其他进程释放它们所持有的资源。在这种情况下,没有任何进程能够继续执行,除非有外部干预。 2. …...
Ubuntu22.04及以上版本buildroot SIGSTKSZ 报错问题
本文提供一种解决 Buildroot SIGSTKSZ 报错途径 解决途径来源参考:Buildroot error when building with Ubuntu 21.10 其出现原因在于 GNU C Library 2.34 release announcement: Add _SC_MINSIGSTKSZ and _SC_SIGSTKSZ. When _DYNAMIC_STACK_SIZE_SOU…...
postgresql数据库基本操作
1. 连接 PostgreSQL 数据库 首先,使用 psql 命令行工具连接到数据库。如果是本地连接,命令格式如下: psql -U postgres -d <数据库名称> -h <主机地址>其中: -U postgres:表示以 postgres 用户身份登录…...
【运维】构建基于Python的自动化运维平台:用Flask和Celery打造高效管理工具
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着企业IT基础设施的复杂性不断增加,手动运维已无法满足高效管理的需求。本文详细介绍如何基于Python构建一个自动化运维平台,利用Flask…...
ES6入门---第三单元 模块三:async、await
async function fn(){ //表示异步:这个函数里面有异步任务 let result await xxx //表示后面结果需要等待 } 读取文件里数据实例: const fs require(fs);//简单封装 fs封装成一个promise const readFile function (fileName){return…...
洛谷 P2866 [USACO06NOV] Bad Hair Day S
题目描述 农夫约翰有 N 头奶牛正在过乱头发节。 每一头牛都站在同一排面朝右,它们被从左到右依次编号为 1,2,⋯,N。编号为 i 的牛身高为 hi。第 N 头牛在最前面,而第 1 头牛在最后面。 对于第 i 头牛前面的第 j 头牛,如果 hi>hi1…...
TS 变量类型生成
TS简单类型注解 let count:number 15 let myName:string MIO let isLoading:boolean false let a:null null let b:undefined undefined let s:symbol Symbol()console.log(hello ts)TS数组类型 数组类型两种写法: 问题:数组中只能存在单一类型数…...
工业大模型:从设备诊断到工艺重构
引言 工业大模型正在引发制造业认知革命。据埃森哲研究,到2026年全球工业大模型市场规模将突破280亿美元,其中工艺优化应用占比达42%。本文将系统解析工业大模型的"预训练-领域适配-应用落地"技术路径,并通过设备健康诊断与工艺参数生成的实践案例,展示如何构建…...
【项目篇之统一内存操作】仿照RabbitMQ模拟实现消息队列
我们的操作分为两种,一种是在内存上进行统一的操作,一种是在硬盘上面操作,今天我写的文章是编写了一个MemoryDataCenter类来实现了 在内存上面的统一操作: 实现统一内存操作 如何使用内存来组织数据 创建一个类来统一管理内存上的…...
强化学习机器人模拟器——GridWorld:一个用于强化学习的 Python 环境
GridWorld 是一个为强化学习(Reinforcement Learning, RL)实验设计的多功能 Python 环境。它提供了一个可定制的二维网格,智能体(agent)需要从起始位置导航到目标位置,避开障碍物、穿越泥泞单元格并收集奖励。本篇博客将详细介绍 grid_world.py 代码中实现的 GridWorld 环…...
DeepSeek Copilot idea插件推荐
🌌 DeepSeek Copilot for IntelliJ IDEA 让 AI 成为你的编程副驾驶,极速生成单元测试 & 代码注释驱动开发! 🚀 简介 DeepSeek Copilot 是一款为 IntelliJ IDEA 打造的 AI 编程助手插件,它能够智能分析你的代码逻辑…...
vue-cropper实现图片裁剪
一、什么是vue-cropper? Vue-Cropper 是一个基于 Vue.js 的图片裁剪组件库,专为 Web 应用设计。当你在网上搜索的时候发现还有一个叫cropper的库,下面是他们的区别: 特性cropper.jsvue-cropper框架依赖纯 JavaScript&am…...
MPI,Pthreads和OpenMP等并行实验环境配置
(假设你已按照文档前面的步骤正确安装了 VMware 和 Ubuntu 20.04) 第一部分:安装 C/OpenMP/Pthreads 环境(修正后) 打开终端: 在 Ubuntu 中启动终端应用程序。 更新软件包列表: sudo ap…...
Spring AI Advisors API:AI交互的灵活增强利器
Spring AI Advisors API:AI交互的灵活增强利器 前言 在当今的软件开发领域,随着人工智能技术的飞速发展,将AI融入应用程序变得越来越普遍。Spring AI作为一个强大的框架,为开发者提供了便捷的方式来实现这一目标。其中的Advisor…...
排序功法入门指南【江湖算法笔记】
话说江湖风云变幻,各路英雄好汉行走江湖,总得有个名号排行。若问“东邪西毒南帝北丐”谁强谁弱,总得排个座次不是?这排序之道,恰似武功秘籍,练好了能号令群雄,练岔了怕是要被笑掉大牙࿰…...
Free Draft Model!Lookahead Decoding加速大语言模型解码新路径
Free Draft Model!Lookahead Decoding加速大语言模型解码新路径 大语言模型(LLMs)在当今AI领域大放异彩,但其自回归解码方式锁死了生成效率。本文将为你解读一种全新的解码算法——Lookahead Decoding,它无需Draft Mo…...
Spring AI 实战:第八章、Spring AI Tool Calling之与时俱进
引言:AI的"知识截止日期"尴尬 如果你想问大模型"明天是星期几?",猜猜TA会怎么答复你~ @GetMapping("/tools/simple/test") public String simpleTest() {return chatClient.prompt...
PyTorch数据集与数据集加载
PyTorch中的Dataset与DataLoader详解 1. Dataset基础 Dataset是PyTorch中表示数据集的抽象类,我们需要继承它并实现两个关键方法: from torch.utils.data import Datasetclass CustomDataset(Dataset):def __init__(self, data, labels):""…...
探秘 Git 底层原理:理解版本控制的基石
Git 是一款开源的分布式版本控制系统,在软件开发领域广泛应用,能有效管理项目的版本变更,Git 已经成为了版本控制的代名词。日常使用中,我们通过git commit提交代码,用git push推送变更,这些便捷操作背后&a…...
chili3d调试10 网页元素css node deepwiki 生成圆柱体 生成零件图片
.input是input的外框,.input input是input的内框 沙雕 全部input都换成textarea了 自己的方法用接口定义,把自己的方法pub出去,定义在内部拉出去只是取个值 这其实是mainwindow端pub回来的 窗口pub端把数据pub回 mainwindow端让mainwindow端…...
【计网】互联网的组成
回顾: 互联网(Internet):它是一个专有名词,是一个特定的互连网,它是指当下全球最大的、最开放的、由众多网络相互连接而形成的特定的的互连网,采用TCP/IP协议族作为通信规则。 一、互联网的组成部分 从互联网的工作方…...
Go语言接口实现面对对象的三大特征
一.知识回顾 在 Go 语言中,接口是一种强大的抽象机制,它允许我们定义一组方法签名,任何类型只要实现了这些方法,就被视为实现了该接口。接口的实现是隐式的,这意味着类型不需要显式声明它实现了某个接口,只…...
TS 字面量类型
str是string类型l str2是常量,类型是字面量类型 用途:配合联合类型确定更严谨精确的可选值利恩...
langchain中 callbacks constructor实现
目录 代码代码解释代码结构代码功能 类似例子 代码 from typing import Any, Dict, Listfrom langchain_openai import ChatOpenAI from langchain_core.callbacks import BaseCallbackHandler from langchain_core.messages import BaseMessage from langchain_core.outputs …...
小土堆pytorch--tensorboard的使用
小土堆pytorch--tensorboard的使用 小土堆pytorch--tensorboard的使用0.介绍1.使用tensorboard绘制 y x 等简单函数1.1 相应的代码1.2 对上述代码的解释1.3 可能遇到的问题1.3.1 问题1.3.2 解决方法 2.使用tensorboard加载数据集中的图片2.1 相应代码2.2 对上述代码的解释2.2.…...
从 0 到 1:使用 Jetpack Compose 和智能自动化实现高效 Android UI 开发
现代 Android UI 开发正逐步从命令式 XML 向声明式 Compose 转变。Compose 凭借其简洁、高效、易测试的特点,能够让开发者更专注于界面和业务逻辑,而不必陷入大量模板化的代码。手把手带你构建一个完整的 Todo List 应用,并演示如何借助自动化…...
学习黑客 week1周测 复盘
Day 7 – 周测 & 复盘 今天任务: 完成 10 道快测题,涵盖 Week 1 的核心知识点:《CIA 三要素》、OWASP Top 10、MITRE ATT&CK、NIST RMF、Linux 权限、TCP/IP、网络安全法、“黑客五阶段” 与风险管理。撰写 300 字周总结…...
【五一培训】Day 3
Topic 1:元学习 一、概念:learn to learn 区分少样本学习与元学习 少样本学习(Few-shot learning)是元学习的一个重要应用,它指的是机器能够在仅有少量样本的情况下,成功地学习和泛化到新任务上。在许多现…...
C++继承详讲
1.继承的概念 继承是实现代码复用的手段,它允许程序员在保持基类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。 2.继承和组合 1.继承体系下,子类对象包含父类的成员。组合体系下,子类对象包含…...
第四节:OpenCV 基础入门-第一个 OpenCV 程序:图像读取与显示
一、引言:为什么选择 OpenCV? 在计算机视觉领域,OpenCV(Open Source Computer Vision Library)是一个开源的、跨平台的计算机视觉库,广泛应用于图像处理、模式识别、机器学习等领域。它支持多种编程语言&a…...
基于PHP实现的easy管理系统
easy管理系统 2.0.1 easy管理系统 是一个多功能的 Web 管理平台,旨在简化项目管理、文件共享和协作流程。它集成了大创项目管理、在线文档生成、代码托管等多种功能,并提供了用户管理、系统设置、日志查看等后台管理能力。 ✨ 功能特性 统一管理平台:…...
ios systeam introduction
Here is an in-depth look at Apple’s iOS, from its inception to its latest major release, covering architecture, core components, security, app lifecycle, development tools, and the headline features of iOS 18. iOS began life as “iPhone OS,” unveiled alo…...
【论文阅读】LLMOPT:一种提升优化泛化能力的统一学习框架
文章目录 第一遍一、摘要二、关键词三、预知识1. 什么是优化泛化问题2. 什么是消融研究3. model alignment(模型对齐) 第二遍:了解论文论点一、研究背景与目的二、相关工作三、LLMOPT框架四、METHODOLOGY(方法论)1. 数据处理2. 学习过程3. 自…...