【Linux内核大揭秘】程序地址空间

在这里插入图片描述

文章目录

  • 什么是程序地址空间
    • 地址空间的组成
    • 虚拟内存技术
  • 如何理解程序地址空间
    • 页表
    • 页表的细节
    • 关于堆区
  • 在Linux中如何查看各个分段的信息
  • 总结

什么是程序地址空间

程序地址空间是一个程序在执行期间可以访问的内存范围。它由操作系统为每个进程分配,以确保进程之间不会相互干扰。地址空间包含了程序所需的所有内存区域,包括代码、已初始化和未初始化的数据、堆(heap)、栈(stack)等。

地址空间的组成

地址空间分为逻辑地址物理地址两种:

  • 逻辑地址:是程序在代码中使用的地址,不直接对应物理内存。每个进程都有独立的逻辑地址空间。
  • 物理地址:是真正存储在内存中的位置。

虚拟内存技术

通过虚拟内存技术,操作系统将逻辑地址映射到物理地址。这种技术带来了以下优势:

  1. 内存隔离:每个进程可以使用相同的逻辑地址空间,而操作系统会隔离各自的实际内存,确保进程之间不会互相影响。
  2. 安全性和稳定性:这种隔离机制使得进程无法直接访问其他进程的内存,提高了系统的安全性和稳定性。

总结来说,程序地址空间通过虚拟内存和地址映射技术实现了进程的内存隔离,保障了多任务操作系统的安全和可靠性。

如何理解程序地址空间

通过一个现象来了解什么是虚拟内存技术。
下面写一个简单的程序:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int gval=100;
int main()
{printf("我是一个进程:pid:%d,ppid:%d\n",getpid(),getppid());pid_t id = fork();if(id==0){//childwhile(1){printf("我是子进程,pid:%d,ppid:%d,gval:%d,&gval:%p\n",getpid(),getppid(),gval,&gval);gval++;sleep(1);}}else{//parentwhile(1){printf("我是父进程,pid:%d,ppid:%d,gval:%d,&gval:%p\n",getpid(),getppid(),gval,&gval);sleep(1);}}return 0;
}

这个程序很简单,通过父进程创建了一个子进程,然后用一个全局变量来证明虽然父子进程共用一套代码,但是数据是分离开的。
我们分别打印全局变量的数据和全局变量的地址,然后子进程对应的全局变量需要做++操作。
我们来看看运行结果:
在这里插入图片描述
可以看见两个全局变量的地址是相同的,但是还是做到了数据独有呢?这是怎么做到的,通过这个现象,我们可以看出gval的地址肯定不是物理内存的地址,如果是物理内存的地址,如果地址相同,那么值也应该相同,所以这里面肯定是用什么结构把真实的物理内存给保护起来了,首先我们来看看我们以前学过的内存的结构。
在这里插入图片描述

这是我们以前了解到的内存的划分区域,从上面现象可以推出这不是程序地址空间,而是进程地址空间,操作系统为每个进程绘制了一个虚拟地址内存,让每个进程以为自己独占整个内存,进程彼此之间是不知道的,从而达到了一定程度上的隔离。
实际上所谓的进程虚拟地址空间本质上是一个内核数据结构(内似于PCB)。
这个内核数据结构叫做mm_struct,在PCB中有一个指针指向虚拟地址空间,PCB控制着这个虚拟地址空间,然后mm_struct通过映射,映射到真实的物理内存上。
我们画一个简图来理解这个概念:
在这里插入图片描述
如何证明确实在task_struct中有这样一个结构体指针呢,我们来看看Linux内核的原码:
在这里插入图片描述

可以看见task_struct内部确实有一个这样的指针,我们来看看mm_struct内部是什么样的:
在这里插入图片描述
可以看见在mm_struct中有一些start和end的成员变量,这些就代表各个区域的起始位置和末尾位置,地址也是一个数,所以我们可以用一个unsigned long类型来表示每个区域的起始位置和末尾位置。
在这里插入图片描述
虽然我们知道我们取到的地址不是物理内存地址,而是虚拟内存地址,中间是通过一层映射关系来将虚拟内存地址转化为物理内存地址的,那中间到底是怎么做到的,其实在这中间起着关键作用的,有一个内核数据结构叫做页表。

页表

在这里插入图片描述

什么是页表:
页表是操作系统内核用来管理虚拟地址和物理地址之间映射的一个数据结构。它的核心作用是支持虚拟内存,使得每个进程可以在自己的独立虚拟地址空间中运行,增强了内存隔离和安全性。
简单了解完页表后,我们来解释一下我们刚刚的现象,为什么父进程的gval不变,子进程的gval在改变,两个gval都指向同一块空间。
在这里插入图片描述
首先父进程创建子进程会以自己为模版创建一个PCB,内核会为子进程创建一个新的mm_struct,mm_struct的大部分字段和和父进程共享,页表也会被创建,所以这里物理地址指向的是同一块空间。
但是当我们修改gval的时候,物理内存会发生写实拷贝,父子进程不再共享gval。
在这里插入图片描述
子进程的gval对应的虚拟地址对应的页表的映射会改变,改变为写实拷贝过后的地址,这样当修改gval时,gval会修改,但是父进程的gval不会被修改,但是gval的地址都是相同的,是因为这是虚拟地址,子进程是以父进程为模版创建的。

页表的细节

关于页表,其实页表不存储物理地址和虚拟地址。
在这里插入图片描述
当中还存在权限的管理和标记位等等属性,这个权限管理指的是读写权限,就比如我们在C语言中遇到的下图:
在这里插入图片描述
这个都知道会崩溃,但是为什么会崩溃,其实是因为str对应的权限只有读,没有写的权限,所以会直接崩溃,这时系统层面上的错误,不是语法层面上的错误,所以语法是不会报错的。
有效位表示看目标数据是否存在于内存当中,如果该位为 0,意味着页面不在物理内存,访问该页面会触发缺页中断,操作系统会加载页面或进行错误处理。
页表其实还有很多属性,这里只陈述这两个属性。

关于堆区

我们new出来的空间是否是物理内存?—答案很显然不是的。
我们new或者malloc出来的空间也是虚拟内存,有一个问题就来了,结构体就那么大,但是堆区是动态的,那他是如何实现动态开辟的呢,刚刚我们提到了mm_struct有一段区域是存储begin和end的,我们只需要改变end和begin的数字,即可控制虚拟内存。
在这里插入图片描述

在Linux中如何查看各个分段的信息

readelf -S 文件名

在这里插入图片描述

总结

通过本篇文章,我们了解了 Linux 程序地址空间的基本结构和分布,包括代码段、数据段、堆、栈以及内核空间的划分。掌握程序地址空间的布局不仅能帮助我们理解进程的内存使用,还能为调试、性能优化和内存管理打下坚实基础。理解 mm_struct、页表以及写时复制等机制,也为深入探索操作系统内核的内存管理提供了关键的思路。希望这些内容能让你在实际开发和学习中更好地应用这些知识,为系统性能和安全性提供支持。

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

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

相关文章

C++ 数据结构 静态顺序表、动态顺序表。

静态顺序表&#xff08;Static Array List&#xff09;是一种线性数据结构&#xff0c;通常用数组实现。它具有固定的大小&#xff0c;并在编译时分配内存。以下是静态顺序表的一些基本概念和实现示例。 静态顺序表基本概念 固定大小&#xff1a;静态顺序表的大小在创建时定义…

pgsql表分区和表分片设计

在设计 PostgreSQL 表分区和表分片时&#xff0c;主要目标是提高查询性能、可扩展性和数据管理的效率。以下是一些关键的设计步骤和策略&#xff1a; 1. 分区策略 水平分片&#xff1a;选择按日期进行水平分片&#xff0c;每天一个分片。这种策略适用于具有时间序列数据的场景…

AnaTraf | 网络性能监测系统与分布式性能监测探秘

AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 对于 IT 运维人员来说&#xff0c;维护网络的稳定和业务的连续性是至关重要的使命&#xff0c;而优化网络性能以及在网络出现故障时快速排除故障则是实现这一使命的关键能力。 一、网络性能监测系统&#x…

C#语言入门:从基础到进阶

C#&#xff08;发音为"C sharp"&#xff09;是微软公司推出的一种面向对象的编程语言&#xff0c;它由Anders Hejlsberg和他的团队在.NET框架下开发。C#语言结合了C和Java的特性&#xff0c;并添加了新的功能&#xff0c;使其成为当今最流行的编程语言之一。 C#的特…

npm入门教程18:npm发布npm包

一、准备工作 注册npm账号&#xff1a; 前往npm官网注册一个账号。注册过程中需要填写个人信息&#xff0c;并完成邮箱验证。 安装Node.js和npm&#xff1a; 确保你的计算机上已安装Node.js和npm。Node.js的安装包中通常包含了npm。你可以通过运行node -v和npm -v命令来检查它…

【论文阅读】Associative Alignment for Few-shot Image Classification

用于小样本图像分类的关联对齐 引用&#xff1a;Afrasiyabi A, Lalonde J F, Gagn C. Associative alignment for few-shot image classification[C]//Computer Vision–ECCV 2020: 16th European Conference, Glasgow, UK, August 23–28, 2020, Proceedings, Part V 16. Spri…

SpringBoot-Velocity模板引擎-快速入门

Velocity-快速入门 一 介绍 Apache Velocity 是一个基于 Java 的模板引擎&#xff0c;它允许任何人使用简单而强大的模板语言来引用对象数据&#xff0c;并生成基于文本的输出。Velocity 最初是作为 WebMacro 项目的一部分开发的&#xff0c;后来成为一个独立的开源项目&…

Docker 安装使用操作指南

Docker 是一种开源的容器化平台&#xff0c;它允许开发者将应用及其所有依赖项打包到一个轻量级的容器中&#xff0c;这样就可以在任何地方一致地运行它们。无论是开发环境、测试环境还是生产环境&#xff0c;Docker 都能够提供一致的环境&#xff0c;从而消除“在我的机器上能…

UE5之5.4 第一人称示例代码阅读2 子弹发射逻辑

TP_WeaponComponent.h 看看头文件 暴露了attach weapon和fire给蓝图 这两个函数意义一看名字吧&#xff0c;就是捡起来枪的时候执行&#xff0c;一个就是发射子弹的时候执行 #pragma once#include "CoreMinimal.h" #include "Components/SkeletalMeshComponen…

飞机布雷盖航程公式

飞机布雷盖航程公式 1. 喷气式飞机布雷盖航程公式推导2. 螺旋桨飞机布雷盖航程公式推导3. 喷气式飞机与螺旋桨飞机的差异分析3.1 喷气式飞机的推力产生机制3.2 螺旋桨推进推力产生机制 布雷盖航程公式&#xff08;Breguet Range Equation&#xff09;是描述飞行器巡航飞行阶段航…

智能合约分享

智能合约练习 一、solidity初学者经典示例代码&#xff1a; 1.存储和检索数据&#xff1a; // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 声明 Solidity 编译器版本// 定义一个名为 SimpleStorage 的合约 contract SimpleStorage {// 声明一个公共状态变量 d…

绿色智慧冻结 专精深地空间:全国冻结法施工技术交流研讨会即将在京召开

2024年10月29日&#xff0c;由中国煤炭工业协会、中国煤炭建设协会、中国中煤能源集团有限公司主办&#xff0c;中煤建设集团有限公司、中煤邯郸特殊凿井有限公司承办的全国冻结法施工技术交流研讨会将在北京黄河京都会议中心隆重召开。研讨会将以“绿色智慧冻结 专精深地空间”…

CSGO: Content-Style Composition in Text-to-Image Generation(代码的复现)

文章目录 CSGO简介论文的代码部署需要下载的模型权重&#xff1a;复现中存在的一些问题 推理代码生成结果示意图 CSGO简介 CSGO: Content-Style Composition in Text-to-Image Generation&#xff08;风格迁移&#xff09; 本文是一篇风格迁移的论文&#xff1a;将内容参考图像…

[nssround#4 swpu]1zweb

能上传文件和查看文件 非预期:出题人没有对读取文件做限制&#xff0c;导致了目录穿越&#xff0c;可直接读取flag 预期解如下&#xff1b; 首先读取index.php与upload.php php <?php //index.php class LoveNss{ public $ljt; public $dky; public $cmd;…

(9)位运算

1. 位运算的概念 位运算操作的是整数在内存中的二进制位。C 语言提供了以下几种位运算操作符&#xff1a; 按位与&#xff08;&&#xff09; 运算规则&#xff1a;将两个操作数对应的二进制位进行与运算。只有当两个对应位都为 1 时&#xff0c;结果位才为 1&#xff0c…

Jmeter命令监控CPU等指标

JMeter 命令行执行脚本得到的报告中&#xff0c;是没有CPU、内存使用率等监控数据的&#xff0c;但是可以使用JMeter插件帮忙。 一、下载jmeter-plugins-manager.jar 下载后将文件放到jmeter安装包lib/ext目录下。打开Jmeter》菜单栏》选项》Plugins Manager 二、安装PerfMon…

江协科技STM32学习- P32 MPU6050

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

原生html+js+css+php多图上传带预览可增删判断图片大小和后缀

原生htmljscssphp多图上传带预览可增删&#xff0c;前后端判断图片大小和后缀 源码来自AI&#xff0c;有改动&#xff0c;整合亲测可用 <?php // 设置允许的最大文件大小为 2MB $maxFileSize 2 * 1024 * 1024; $allowedExtensions [jpg, jpeg, png, gif];// 上传目录&am…

java设计模式之创建者模式(5种)

设计模式 软件设计模式&#xff0c;又称为设计模式&#xff0c;是一套被反复利用&#xff0c;代码设计经验的总结&#xff0c;他是在软件设计过程中的一些不断发生的问题&#xff0c;以及该问题的解决方案。 **创建者模式又分为以下五个模式&#xff1a;**用来描述怎么“将对象…

如何一键更换ppt模板?掌握这2个ppt技巧快速搞定!

每当要制作ppt&#xff0c;很多人会第一时间去搜刮各种ppt模板&#xff0c;有时我们找到了一份貌似符合需求的模板&#xff0c;等到了ppt制作环节&#xff0c;才发现离我们的预期相距甚远&#xff0c;做到一半的ppt如何换模板呢&#xff1f; 想要在中途更换ppt模板&#xff0c;…