【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,一经查实,立即删除!

相关文章

【论文阅读】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;后来成为一个独立的开源项目&…

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

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

智能合约分享

智能合约练习 一、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;…

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;…

操作系统笔记(五)信号量,经典的IPC问题(读写者问题...)

信号量 一个信号量是一个包含两部分内容的数据结构&#xff1a; (a) 一个整数计数器, COUNT (b) 一个记录阻塞进程ID的队列, Q 信号量有两个原子操作&#xff1a; UP(V操作&#xff09; 和 DOWN (P操作) DOWN(S): if (S.count > 0) S.count …

臻于智境 安全护航 亚信安全受邀出席新华三智算新品发布会

近日&#xff0c;紫光股份旗下新华三集团在北京隆重举办了主题为“乘势 进化 臻于智境”的新华三智算新品发布会。作为新华三集团的长期战略合作伙伴&#xff0c;亚信安全受邀参会&#xff0c;亚信安全CEO马红军出席发布仪式&#xff0c;并与来自各界的业界伙伴共同探讨智能化…

【解决】Ubuntu18.04 卸载python之后桌面异常且终端无法打开,重启后进入tty1,没有图形化界面

我因为python版本太过于混乱 &#xff08;都是为了学习os&#xff09; &#xff0c;3.6—3.9版本我都安装了&#xff0c;指向关系也很混乱&#xff0c;本着“重装是最不会乱”的原则&#xff0c;我把全部版本都卸载了。然后装了3.9 发现终端打不开了&#xff0c;火狐浏览器的图…

2-140 基于Solidworks和Matlab Simulink Simscape仿真的机器人手臂仿真

基于Solidworks和Matlab Simulink Simscape仿真的机器人手臂仿真&#xff0c;使用Simulink-Simscape Multibody模块&#xff0c;完成SW-Simscape-Multibody-Link-Plugin手臂仿真&#xff0c;通过调节关节实现手臂动作&#xff0c;并显示三坐标位置。程序已调通&#xff0c;可直…

流媒体协议.之(RTP,RTCP,RTSP,RTMP,HTTP)(一)

闲着没事做&#xff0c;记录一下开发项目用过的协议&#xff0c;项目中&#xff0c;大多是是实时显示播放的&#xff0c;通过私有协议&#xff0c;传输到上位机&#xff0c;实时播放&#xff0c;延时小于200ms&#xff0c;仿照这些协议&#xff0c;定义的数据格式。如果用这些协…

通过思维导图【脑图】梳理Java 开发技术栈

通过思维导图【脑图】梳理Java 开发技术栈 前言一、思维导图概述二、Java 开发技术栈1.整体脑图结构2.基础知识3.核心语法4.高级特性5.常用框架6.数据库7.算法8.设计模式9.最佳实践10.资源推荐 附思维导图原件总结我是将军我一直都在&#xff0c;。&#xff01; 前言 将军深刻…

Mac “屏幕保护程序启动或显示器关闭后需要密码“无效

屏幕保护程序启动或显示器关闭后需要密码只能选择“立即”的解决方法&#xff1a; 在 iPhone mirror中设置&#xff0c;每次询问权限。 参考&#xff1a;https://support.apple.com/en-us/120421

基于matlab的凸包(Convex Hull)算法理解与测试

基于matlab的凸包Convex Hull算法理解与测试 0 引言1 Graham扫描算法原理2 Graham扫描算法实现3 Graham扫描算法关键函数4 结语 0 引言 &#x1f4bb;&#x1f4bb;AI一下&#x1f4bb;&#x1f4bb; 凸包算法是计算给定点集的最小凸包的一种算法。凸包是包含给定点集中所有点…