Linux学习笔记之虚拟地址空间

news2025/4/12 8:09:46

1.示例引入

        运行如下代码那么运行结果如下图。

#include<stdio.h>
#include<unistd.h>

int main()
{

    pid_t id =fork();
    if(id==-1)
    {
        printf("创建进程错误!\n");
        return 1;
    }

    int size=0;
    if(id==0)
    {
        //子进程
        while(1)
        {
             
             printf("我是子进程,id为:%d,size=%d,size地址为%p\n",getpid(),size++,&size);
             sleep(1);
        }
    }
    else
    {
        //父进程
        while(1)
        {
             printf("我是父进程,id为:%d,size=%d,size地址为%p\n",getpid(),size,&size);
             sleep(1);
        }
    }

    return 0;
}

        结果会大吃一惊,相同地址的值竟然不同,这和C语言学习时的理论相违背,内存最小寻址单位是字节,给每个字节编号,指针指向其中某个字节编号。但是运行结果是相同指针,读取内存不一样。

2.虚拟地址空间

        这是因为Linux操作系统没有采用让进程直接操作物理内存的方式,而是采用给进程一块虚拟空间,让进程间接访问物理内存,如下图。

                这样就可以解释上述代码,虽然他们的虚拟地址相同,但是经过OS映射后的实际物理地址不同,所以才会出现地址相同而值不同的情况。

        2.1 虚拟地址如何实现

        在c语言中常常会涉及到如下内存概念,堆区,栈区,代码区,常量区等。

        一个地址我们如何判断他在那个内存分区,一种方法是根据代码分析,malloc申请的在堆区,数组在栈区,还有一种方式就是打印堆区和栈区的变量地址,一般而言两者相差会十分大,看地址和那个更加接近,就处在那个区域。

#include<stdio.h>
#include<stdlib.h>

int gval = 10;
int main()
{
    const char* p1 = "aaaa";

    int* p2 = (int*)malloc(12);
    int a = 10;
    int* p3 = &a;

    printf("常量区%p 全局变量区%p 堆区%p 栈区%p",p1,&gval,p2,p3);

    return 0;
}

        实际上对于进程来说,只要我们知道堆区开始位置地址和结束位置地址就可以判断出当前变量处在那里了。我们管理不同分类的内存,只需要管理不同内存区域的开始与结束就行了。在Linux内核中就封装了mm_struct结构体管理进程内存,每个进程结构体内包含mm_struct结构体。

struct mm_struct {
    // 保护该结构体的自旋锁,用于并发访问控制
    spinlock_t mmap_lock;

    // 虚拟内存区域链表的头节点
    struct vm_area_struct *mmap;

    // 用于管理虚拟内存区域的红黑树的根节点
    struct rb_root mm_rb;

    // 虚拟内存区域的数量
    unsigned long map_count;

    // 代码段的起始地址
    unsigned long start_code, end_code;

    // 数据段的起始地址和结束地址
    unsigned long start_data, end_data;

    // 堆的起始地址
    unsigned long start_brk;

    // 堆的当前结束地址
    unsigned long brk;

    // 栈的起始地址
    unsigned long start_stack;

    // 命令行参数的起始地址
    unsigned long arg_start, arg_end;

    // 环境变量的起始地址和结束地址
    unsigned long env_start, env_end;

    // 页全局目录(Page Global Directory)指针
    pgd_t *pgd;

    // 内存管理上下文
    mm_context_t context;

    // 引用计数,记录有多少个地方引用了该 mm_struct
    atomic_t mm_users;

    // 映射计数,记录有多少个进程映射了该内存空间
    atomic_t mm_count;

    // 锁,用于保护对该结构体的读写操作
    struct rw_semaphore mmap_sem;

    // 链表节点,用于将该 mm_struct 加入到全局的 mm_struct 链表中
    struct list_head mmlist;

    // 用于跟踪内存管理操作的统计信息
    struct mm_rss_stat rss_stat;
};

        由此便可以划分出C语言的内存布局。

2.2 页表

        页表其实就是虚拟地址和实际物理地址之间的桥梁,他类似于hash一样,如下图。

        物理内存都是一样的,但是C语言划分的不同内存区域属性不同,例如代码区不可修改,栈区内存有限,这都要进程额外的维护起来。因此除了保留物理地址外,页表也会保留这块地址的属性,包括读,写,是否有效等信息

        由此便可以进行一定程度的保护,假如向一块只读内存写入数据,系统就会直接结束进程,弹出错误。所谓的野指针从页表的角度解读就是指定地址无效,或者是只读权限。

3.虚拟地址空间意义

        3.1 保护内存安全

        如果允许用户直接访问物理内存,那么便可以修改指定内存的数据,这极大可能会造成数据的错乱,程序运行崩溃,反观使用虚拟内存加页表的形式,可以最大程度的保护操作系统,用户在使用非法访问的时候直接禁止掉,不会对操作系统产生威胁

        3.2 解耦合

        通过虚拟地址实现了进程管理与内存管理的分离,这样在进程使用内存的时候就不用关心内存够不够,是否可用的问题了,这样使管理方面变得简单。

        3.3 有序

        如果没有虚拟地址空间,多个进程在内存运行,那么每个进程申请的空间必定是七零八落的,东一块,西一块,管理起来十分的麻烦。但是经过虚拟地址空间之后,整个进程的空间布局变得明朗起来,分为栈区,堆区,静态区等,有利于学习与管理。

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

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

相关文章

HTTP的“对话”逻辑:请求与响应如何构建数据桥梁?

一、前言 作为现代互联网通信的基石&#xff0c;HTTP协议定义了客户端与服务器之间的“对话规则”。每一次网页加载、API调用或文件传输的背后&#xff0c;都离不开精心构造的HTTP请求与响应。请求中封装了用户的意图——从请求方法、资源路径到提交的数据&#xff1b;响应则承…

[论文阅读] SeeSR: Towards Semantics-Aware Real-World Image Super-Resolution

文章目录 一、前言二、主要贡献三、Introduction四、Methodology4.1 Motivation &#xff1a;4.2Framework Overview.** 一、前言 通信作者是香港理工大学 & OPPO研究所的张磊教授&#xff0c;也是图像超分ISR的一个大牛了。 论文如下 SeeSR: Towards Semantics-Aware Rea…

LM Studio笔记

一、什么是 LM Studio&#xff1f; LM Studio 是一款功能强大、易于使用的桌面应用程序&#xff0c;用于在本地机器上实验和评估大型语言模型&#xff08;LLMs&#xff09;。它允许用户轻松地比较不同的模型&#xff0c;并支持使用 NVIDIA/AMD GPU 加速计算。 功能集&#xff1…

Linux CentOS 7部署Vulhub靶场

漏洞复现环境&#xff1a; 1、Linux操作系统中通过Docker部署的Vulhub靶场&#xff1a; docker docker-compose 2、Nmap扫描工具 一、部署靶场 1、安装Docker 1、下载docker yum install docker 安装完成&#xff0c;如下图&#xff1a; 2、开启docker服务 [rootlocalhost…

Golang GORM系列:GORM分页和排序

高效的数据检索和表示是应用程序开发的关键方面。GORM是健壮的Go对象关系映射库&#xff0c;它为开发人员提供了强大的工具来实现这一点。无论你是在构建动态web应用程序还是数据密集型服务&#xff0c;掌握GORM中的分页和排序使您能够提供无缝且高效的用户体验。本文我们将深入…

【怎么使用Redis实现一个延时队列?】

怎么使用Redis实现一个延时队列? 详细说明Java代码示例解释注意事项使用Redis实现延时队列通常通过有序集合(Sorted Set)来实现,利用Redis的ZSET类型及其相关命令可以很方便地实现这一功能。 有序集合中的每个元素都有一个分数(score),我们可以利用这个分数来存储消息需…

HarmonyNext上传用户相册图片到服务器

图片选择就不用说了&#xff0c;直接用 无须申请权限 。 上传图片&#xff0c;步骤和android对比稍微有点复杂&#xff0c;可能是为了安全性考虑&#xff0c;需要将图片先拷贝到缓存目录下面&#xff0c;然后再上传&#xff0c;当然你也可以转成Base64&#xff0c;然后和服务…

宝塔docker 安装oracle11G

1、拉取镜像 sudo docker pull iatebes/oracle_11g #iatebes为用户名2、查看镜像 sudo docker images3、创建并运行容器 docker run -d --privileged --name oralce11g -p 1521:1521 iatebes/oracle_11g4、登录到容器 5、进入容器并修改system用户密码 docker exec -it orac…

计算机视觉-OpenCV图像处理

1.Matplotlib数据可视化&#xff08;绘制图像直方图、可视化矩阵&#xff09; # Matplotlib 数据可视化&#xff08;绘制图像直方图、可视化矩阵&#xff09; # 本节主要讲解如何使用 Matplotlib 绘制图像直方图和可视化矩阵。 # 1. 绘制图像直方图 # 2. 可视化矩阵# 1. 绘制图…

【论文笔记】Transformer^2: 自适应大型语言模型

Code repo: https://github.com/SakanaAI/self-adaptive-llms 摘要 自适应大型语言模型&#xff08;LLMs&#xff09;旨在解决传统微调方法的挑战&#xff0c;这些方法通常计算密集且难以处理多样化的任务。本文介绍了Transformer&#xff08;Transformer-Squared&#xff09;…

【医学影像AI】50个眼科影像数据集(1)分类任务

【医学影像】50个眼科影像数据集&#xff08;1&#xff09;分类任务 【医学影像】50个眼科影像数据集&#xff08;2&#xff09;分割任务 【医学影像】50个眼科影像数据集&#xff08;3&#xff09;其它任务 【医学影像AI】50 个眼科影像数据集&#xff08;1&#xff09;分类任…

2025年-G4--lc75--Best Time to Buy and Sell Stock(java版)

1.题目描述 2.思路 思路1: 3.java代码实现 class Solution {public int maxProfit(int[] prices) {// //初始化最小价格为最大值&#xff0c;最大利润为0// int minPriceInteger.MAX_VALUE;// int maxProfit0;// //遍历价格数组// for (int price : prices)// …

STM32 PWM脉冲宽度调制介绍

目录 背景 PWM 模式 影子寄存器和预装载寄存器 PWM对齐模式 PWM 边沿对齐模式 向上计数配置 向下计数的配置 PWM 中央对齐模式 程序 第一步、使能GPIOB组、AFIO、TIM3外设时钟 第二步、输出通道端口配置​编辑 第三步、定时器配置产生频率 第四步、PWM输出配置 第…

ZYNQ TCP Server PS端千兆网口速率低问题,要修改BSP中LWIP配置参数

用VITIS教程里面 TCP UDP应用工程例程 打算测试PS端千兆网口速率。ZYNQ核心板用黑金的&#xff0c;外部板子自画的网口电路和其它电路。TCP SERVER时 iperf测试速率 只有60~70Mbit/s&#xff1f;然后用UDP SERVER方式&#xff0c;发现能达到 950Mbit/s&#xff1f;&#xff1f;…

毕业设计—基于Spring Boot的社区居民健康管理平台的设计与实现

&#x1f393; 毕业设计大揭秘&#xff01;想要源码和文章&#xff1f;快来私信我吧&#xff01; Hey小伙伴们~ &#x1f44b; 毕业季又来啦&#xff01;是不是都在为毕业设计忙得团团转呢&#xff1f;&#x1f914; 别担心&#xff0c;我这里有个小小的福利要分享给你们哦&…

Visual Studio Code使用ai大模型编成

1、在Visual Studio Code搜索安装roo code 2、去https://openrouter.ai/settings/keys官网申请个免费的配置使用

nlp|微调大语言模型初探索(1),LLaMA-Factory

前言 微调模型通常比从零开始训练一个模型的技术要求低。公司不需要拥有大量的深度学习专家&#xff0c;利用现有的开源工具和库&#xff08;如Hugging Face的Transformers等&#xff09;&#xff0c;中小型公司可以轻松地使用和微调大型模型&#xff0c;从而快速实现AI能力的集…

c++TinML转html

cTinML转html 前言解析解释转译html类定义开头html 结果这是最终效果&#xff08;部分&#xff09;&#xff1a; ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6cf6c3e3c821446a84ae542bcc2652d4.png) 前言 在python.tkinter设计标记语言(转译2-html)中提到了将Ti…

《蓝耘服务器:领先架构、技术创新与行业应用全景解析》

&#x1f31f; 嗨&#xff0c;我是Lethehong&#xff01;&#x1f31f; &#x1f30d; 立志在坚不欲说&#xff0c;成功在久不在速&#x1f30d; &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞⬆️留言收藏&#x1f680; &#x1f340;欢迎使用&#xff1a;小智初学…