【Linux进程篇】Linux内核——程序地址空间的初构

news2024/11/17 9:26:58

W...Y的主页 😊

代码仓库分享💕 


程序地址空间回顾

我们在讲C语言的时候,大家应该都见过这样的空间布局图:

为了更好的验证不同的数据在内存中的存储位置,下面这段代码我们可以去实验一下:

#include<stdio.h>
#include<stdlib.h>
int g_val = 100;
int g_unval;
int main(int argc, char *argv[], char *env[])
{
    printf("code addr: %p\n", main);
    printf("init data addr: %p\n", &g_val);
    printf("uninit data addr: %p\n", &g_unval);

    char *heap = (char*)malloc(20);
    char *heap1 = (char*)malloc(20);
    char *heap2 = (char*)malloc(20);
    char *heap3 = (char*)malloc(20);
    static int c;
    printf("heap addr: %p\n", heap);
    printf("heap1 addr: %p\n", heap1);
    printf("heap2 addr: %p\n", heap2);
    printf("heap3 addr: %p\n", heap3);

    printf("stack addr: %p\n", &heap);
    printf("stack addr: %p\n", &heap1);
    printf("stack addr: %p\n", &heap2);
    printf("stack addr: %p\n", &heap3);
    printf("c addr: %p, c: %d\n", &c, c);

    for(int i = 0; argv[i]; i++)
    {
        printf("&argv[%d]=%p\n", i, &argv[i]); 
    }
    for(int i = 0; env[i]; i++)
    {
        printf("&env[%d]=%p\n", i, &env[i]);
    }

    return 0;
}

 

这就是我们所打印出来的结果,我们可以知道:

1.堆与栈是相对而生的。

2.先有命令行操作符地址再有环境变量的地址 

如果我们想看一下命令行与环境变量存的字符串所在的地址,我们需要稍微修改一下代码:

for(int i = 0; argv[i]; i++)
{
    printf("argv[%d]=%p\n", i, argv[i]); 
}
for(int i = 0; env[i]; i++)
{
    printf("env[%d]=%p\n", i, env[i]);
}

 

 这样我们就能看出无论是表还是表指向的项目,都是在栈空间的上面保存着!!!

而我们的static变量的存储位置在未初始变量与初始化数据直接,说明操作系统已经默认把static变量默认成全局变量了,所以他会在我们进程运行期间一直存在不会被销毁。 

那上面的结构图中的地址,是内存的地址吗?我们再来看一段代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int g_val = 100;
int g_unval;
int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        int cnt = 0;
        //子进程
        while (1)
        {
            printf("child, pid: %d, ppid: %d, g_val: %d, &g_val: %p\n", getpid(), getppid(), g_val, &g_val);
            sleep(1);
            cnt++;
            if (cnt == 5)
            {
                g_val = 200;
                printf("child change g_val: 100->200\n");
            }
        }
    }
    else
    {
        while (1)
        {
            printf("father, pid: %d, ppid: %d, g_val: %d, &g_val: %p\n", getpid(), getppid(), g_val, &g_val);
            sleep(1);
        }

    }
    return 0;
}

因为我们知道父子进程中的变量数据是共享的,现在我们有一个全局变量g_val 等于100,当我们让程序运行5秒后在子进程中修改g_val的内容,将100改到200后,我们在进行观察发现子进程中的g_val被修改成200,而父进程的g_val不变。但是父子进程中的g_val的地址却是相同的!!! 

内容不一样地址却一样???综上所述:这个地址绝对不是内存物理地址!!!

这个地址被叫做虚拟地址或者线性地址。 所以我们所使用的地址全都不是物理地址。我们所打印的地址看到的空间排布不是物理内存。

进程地址空间

地址空间(address space)表示任何一个计算机实体所占用的内存大小。比如外设、文件、服务器或者一个网络计算机。地址空间包括物理空间以及虚拟空间。

物理地址 (physical address): 放在寻址总线上的地址。放在寻址总线上,如果是读,电路根据这个地址每位的值就将相应地址的物理内存中的数据放到数据总线中传输。如果是写,电路根据这个地址每位的值就将相应地址的物理内存中放入数据总线上的内容。物理内存是以字节(8位)为单位编址的。

虚拟地址 (virtual address): CPU启动保护模式后,程序运行在虚拟地址空间中。注意,并不是所有的“程序”都是运行在虚拟地址中。CPU在启动的时候是运行在实模式的,内核在初始化页表之前并不使用虚拟地址,而是直接使用物理地址的。

 所以之前说‘程序的地址空间’是不准确的,准确的应该说成 进程地址空间 ,那该如何理解呢?看图:

这就说明在我们的g_val中子进程先将我们父进程的地址空间进行拷贝,而我们的页表如同我们的hash映射一样,将我们的虚拟地址与物理地址进行映射,所以父子进程的g_val的虚拟地址是相同的。

当我们对子进程的值进行修改时,我们操作系统会在物理内存中开辟另一块空间进行储存,而我们的页表的映射关系也会发生改变。即key的值不会改变但value的值会发生改变。

进程地址空间在每一个进程中都会存在一个进程地址空间,在32位操作系统下的范围是[0,4GB]。

在操作系统下管理地址空间就如同管理硬件或PCB,都是创建一个结构体进行管理的其对应的都是数据结构。

那管理进程空间的结构体里面都有说明数据呢?PCB结构体指令中肯定有一个指针指向管理进程空间的结构体中:

 

上图我只截取了一小部分源码,从中我们可以看出有许多划分空间的指针,这些都是为了划分物理内存的虚拟内存指针,还有记录代码、数据、堆、栈等等开始结束的位置。而区域划分的本质就是区域内的各个地址都可以使用 。

我们的地址空间不具备对我们的代码和数据的保存能力,他们都存在物理空间。而给我们一张进程映射表——页表可以将地址空间转换到物理空间中去。

为什么要有地址空间呢?

1.将物理内存从无序变有序,让进程以统一的视角进行管理

2.将进程管理和内存管理进行解耦合

3.内存地址空间+页表是保证内存安全的重要收段

 malloc/new是如何申请空间的呢?

首先我们就要理解new/malloc的堆空间申请开辟后我们不一定是直接使用的。可能是过去1ms甚至1s后我们才去使用的。但是操作系统的主旨是一定要为效率和资源使用率负责的!!!所以我们经常使用的new/malloc本质先不会直接在物理内存中申请开辟空间,而是在虚拟地址中先进行开辟。但是页表中却没有对应物理地址的映射,只有当我们准备进行写入时才会有对应的物理地址和映射关系的出现!!!

这样做的好处是:

1.充分保证内存的使用率。

2.提升new和malloc的性能


以上就是本次的内容,我们已经学习了进程的基本概念,下篇博客我们将学习如何操作进程,请尽情期待!!! 

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

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

相关文章

眼精星和金鸣识别新增智能结构化识别,助您快速筛选和统计数据

熟悉眼精星票证识别系统或金鸣表格文字识别大师的用户都知道&#xff0c;近日&#xff0c;这二款软件同时上线了“智能结构化”功能&#xff0c;那么&#xff0c;什么是智能结构化呢&#xff1f; 准确地说&#xff0c;我们这里的智能结构化应为OCR智能结构化&#xff0c;因为它…

Docker Hub 国内镜像源配置

Docker Hub 国内镜像源配置 Docker Hub 国内镜像源是指在国内境内提供 Docker 镜像服务的镜像源。由于国际网络带宽等问题&#xff0c;国内用户下载 Docker 镜像通常速度较慢。因此&#xff0c;为了解决这个问题&#xff0c;一些国内的公司和组织提供了 Docker 镜像的国内镜像…

Java核心: 使用instrumentation

在上一篇Java核心: 注解处理器我们提到&#xff0c;通过实现AbstractProcessor&#xff0c;并调用javac -processor能够生成代码来实现特殊逻辑。不过它存在两个明显的问题: 只能新增源文件来扩展逻辑&#xff0c;无法修改现有的类或方法必须有一个单独的编译过程&#xff0c;…

【stm32/CubeMX、HAL库】嵌入式实验六:定时器(1)|定时器中断

参考&#xff1a; 【【正点原子】手把手教你学STM32CubeIDE开发】 https://www.bilibili.com/video/BV1Wp42127Cx/?p13&share_sourcecopy_web&vd_source9332b8fc5ea8d349a54c3989f6189fd3 《嵌入式系统基础与实践》刘黎明等编著&#xff0c;第九章定时器。 实验内容…

【VRIO模型】用战略模型找到你的「核心竞争力」

一个项目或企业要获得成功&#xff0c;其所拥有的资源和资源发挥的效能至关重要。那么&#xff0c;什么样的资源才能支撑项目发展的核心竞争力呢&#xff1f;VRIO是针对组织内部资源与能力&#xff0c;分析竞争优势和弱点的工具。 VRIO模型 VRIO模型是针对企业内部资源与能力…

LeetCode刷题之HOT100之三数之和

2024/5/29 天气真他妈好呀&#xff01;好天气让我舒畅&#xff0c;可惜俺今天把我养护了两三个月的栀子花花苞又整掉了一朵&#xff0c;呜呜呜&#xff01;看着它们一天天长大&#xff0c;花苞边由嫩绿泛白&#xff0c;结果被我不小心弄掉了&#xff0c;我是罪人。它们还想&…

SunoAI 智能创作歌曲神器的源码系统架构 前后端分离 附带完整的源代码包以及安装搭建教程

系统概述 SunoAI 智能创作歌曲神器的源码架构是基于先进的技术理念构建而成。前端采用了现代化的用户界面设计&#xff0c;为用户提供直观、友好的操作环境。后端则运用高效的算法和强大的处理能力&#xff0c;确保歌曲创作的准确性和高质量。 代码示例 系统特色功能模块 1.智…

Vue3 - 实现一个雨水滴落的动画效果

在 Vue 3 中实现一个雨水滴落的动画效果,可以使用 HTML5 的 <canvas> 元素和 JavaScript 来绘制和控制动画。 以下是一个实现雨水滴落效果的示例: 创建一个 Vue 3 项目 首先,确保你已经创建了一个 Vue 3 项目。如果还没有,可以使用 Vue CLI 来创建: vue create r…

如果不花钱,又担心钱存着贬值,怎么办?如果把大部分钱投入到赚钱的事上,特别是自己专业上,比如说我是十年的程序员,帮我分析投资?

如果你不想花钱&#xff0c;但又担心钱存着会贬值&#xff0c;有几个策略可以帮助你在不花费大量金钱的情况下保护你的资金价值&#xff1a; 高收益储蓄账户或货币市场账户&#xff1a; 选择一个高收益的储蓄账户或货币市场账户&#xff0c;这些账户通常比传统储蓄账户提供更高…

[ACL 2024 Main] StickerConv: 从零开始的多模态共情回复生成

文章目录 &#x1f4c3; Abstract&#x1f52d; Contributions&#x1f50d; Approach✨ Agent for StickerConv✨ StickerConv Dataset✨ PEGS✨ 多模态共情回复评价 &#x1f4ca; Experiments&#x1f4c4; Conclusion&#x1f310; 开源网址 Project Page: StickerConv Pro…

【云原生】kubernetes中Configmap原理解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

汽车IVI中控开发入门及进阶(二十一):DAB和FM 收音机

前言: 在过去的十年里,数字收音机对车载娱乐产生了重大影响。现在,几乎每辆新车都标配了这项技术,这也是我们60%以上的人收听收音机的方式。甚至有传言称,在不久的将来,将永久关闭调频发射机,使许多车载收音机过时。但一些相对年轻的汽车在工厂里仍然没有安装DAB,而且…

Linux共享内存创建和删除

最近项目中使用到了共享内存记录下 创建共享内存: 删除共享内存: 代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <u…

服务器数据恢复—异常断电导致ESXi虚拟机无法启动的数据恢复案例

服务器数据恢复环境&#xff1a; 某大厂PS4000服务器&#xff0c;服务器上部署VMware ESXi虚拟化平台。 服务器故障&#xff1a; 机房断电&#xff0c;重启后服务器中的某台虚拟机不能正常启动。管理员查看虚拟机配置文件&#xff0c;发现无法启动的虚拟机的配置文件除了磁盘文…

【全开源】自习室在线订座小程序源码(FastAdmin+ThinkPHP+uView)

打造高效学习空间的必备工具 一、引言&#xff1a;自习室订座难题的解决之道 在如今的学习环境中&#xff0c;自习室成为了学生们备战考试、进行深度学习的重要场所。然而&#xff0c;随着学生人数的增加&#xff0c;自习室座位资源变得日益紧张。为了解决这一难题&#xff0…

SSL证书该如何选择,DV、OV、EV又有什么区别?

选择SSL证书时&#xff0c;您需要根据您的网站性质、安全需求以及预算来决定。DV&#xff08;域名验证&#xff09;、OV&#xff08;组织验证&#xff09;、EV&#xff08;扩展验证&#xff09;是三种不同类型的SSL证书&#xff0c;它们在验证深度、安全性和可见性方面有所差异…

Fastjson 反序列化漏洞[1.2.24-rce]

漏洞复现环境搭建请参考 http://t.csdnimg.cn/vSaaw kali切换jdk版本请参考 Kali安装JAVA8和切换JDK版本的详细过程_kali安装jdk8-CSDN博客 漏洞原理 Fastjson提供的com.sun.rowset.JdbcRowSetImpl类下的dataSourceName方法支持传入一个RMI/LDAP源&#xff0c;支持远程调用。…

走进智慧仓储:3D可视化工厂园区革新物流新纪元

在快节奏的现代生活中&#xff0c;物流仓储行业扮演着至关重要的角色。随着科技的飞速发展&#xff0c;传统仓储模式正面临一场前所未有的变革。今天&#xff0c;就让我们一起看看3D可视化技术如何为物流行业带来前所未有的便利与效率。 什么是3D可视化工厂园区&#xff1f; 3…

ABP框架+Mysql(二)

展示页面--图书列表页面 本地化 开始的UI开发之前,我们首先要准备本地化的文本(这是你通常在开发应用程序时需要做的).本地化文本在前端页面会常用。 本地化文本位于 Acme.BookStore.Domain.Shared 项目的 Localization/BookStore 文件夹下: 打开 en.json (英文翻译)文件并更…

「浏览器」跨站请求伪造CSRF攻击的原理以及防范措施

前言 HTTP 是一个无状态的协议&#xff0c;比如需要账号密码登录的网站这个场景&#xff0c;为了避免每次都需要重复输入&#xff0c;有一种方案就是Cookie&#xff0c;具体使用不做赘述&#xff0c;但是这样带来了一些安全问题。跨站请求伪造&#xff08;CSRF&#xff09;攻击…