【Linux进程(六)】程序地址空间深度实证:从内存布局验证到虚拟化理解的基石


🎬 个人主页艾莉丝努力练剑
专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • [5 ~> 程序 / 进程虚拟地址空间](#5 ~> 程序 / 进程虚拟地址空间)
    • [5.1 研究平台](#5.1 研究平台)
    • [5.2 回顾程序地址空间](#5.2 回顾程序地址空间)
    • [5.3 对程序地址空间各个区域进行分布验证](#5.3 对程序地址空间各个区域进行分布验证)
      • [5.3.1 代码演示](#5.3.1 代码演示)
      • [5.3.2 运行结果](#5.3.2 运行结果)
      • [5.3.3 两个问题探究](#5.3.3 两个问题探究)
        • [5.3.3.1 问题1:`char *s ="hello world";*s = 'H"`为什么不可以修改?](#5.3.3.1 问题1:char *s ="hello world";*s = 'H"为什么不可以修改?)
        • [5.3.3.2 问题2:static(静态)修饰局部变量:作用域不变,生命周期变成全局(?)](#5.3.3.2 问题2:static(静态)修饰局部变量:作用域不变,生命周期变成全局(?))
    • [5.3 程序地址空间初识思维导图](#5.3 程序地址空间初识思维导图)
  • 结尾


5 ~> 程序 / 进程虚拟地址空间

堆、栈相对而生!

堆就是堆,栈就是栈,堆栈是栈。

5.1 研究平台

5.2 回顾程序地址空间

艾莉丝在介绍C语言部分的时候,应该给大家展示过这样的空间布局图------

之前可能是这样一张图------

5.3 对程序地址空间各个区域进行分布验证

但是其实我们对它并不理解,所以,为了铺垫下面的内容,我们先对程序地址空间各个区域进行分布验证------

5.3.1 代码演示

c 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int g_unval;
int g_val = 100;

int main(int argc, char *argv[], char *env[])
{
    const char *str = "helloworld";
    //*str = 'H';
    printf("code addr: %p\n", main);
    printf("init global addr: %p\n", &g_val);
    printf("uninit global addr: %p\n", &g_unval);

    static int test = 10;
    char *heap_mem = (char*)malloc(10);
    char *heap_mem1 = (char*)malloc(10);
    char *heap_mem2 = (char*)malloc(10);
    char *heap_mem3 = (char*)malloc(10);
    printf("heap addr: %p\n", heap_mem); //heap_mem(0), &heap_mem(1)
    printf("heap addr: %p\n", heap_mem1); //heap_mem(0), &heap_mem(1)
    printf("heap addr: %p\n", heap_mem2); //heap_mem(0), &heap_mem(1)
    printf("heap addr: %p\n", heap_mem3); //heap_mem(0), &heap_mem(1)

    printf("test static addr: %p\n", &test); //heap_mem(0), &heap_mem(1)
    printf("stack addr: %p\n", &heap_mem); //heap_mem(0), &heap_mem(1)
    printf("stack addr: %p\n", &heap_mem1); //heap_mem(0), &heap_mem(1)
    printf("stack addr: %p\n", &heap_mem2); //heap_mem(0), &heap_mem(1)
    printf("stack addr: %p\n", &heap_mem3); //heap_mem(0), &heap_mem(1)

    printf("read only string addr: %p\n", str);
    for(int i = 0 ;i < argc; 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;
}

//#include <stdio.h>
//#include <unistd.h>
//#include <stdlib.h>
//
//int g_unval;
//int g_val = 100;
//
//int main(int argc, char *argv[], char *env[])
//{
//    const char *str = "helloworld";
//    printf("code addr: %p\n", main);
//    printf("init global addr: %p\n", &g_val);
//    printf("uninit global addr: %p\n", &g_unval);
//    
//    static int test = 10;
//    char *heap_mem = (char*)malloc(10);
//    char *heap_mem1 = (char*)malloc(10);
//    char *heap_mem2 = (char*)malloc(10);
//    char *heap_mem3 = (char*)malloc(10);
//    printf("heap addr: %p\n", heap_mem); //heap_mem(0), &heap_mem(1)
//    printf("heap addr: %p\n", heap_mem1); //heap_mem(0), &heap_mem(1)
//    printf("heap addr: %p\n", heap_mem2); //heap_mem(0), &heap_mem(1)
//    printf("heap addr: %p\n", heap_mem3); //heap_mem(0), &heap_mem(1)
//    
//    printf("test static addr: %p\n", &test); //heap_mem(0), &heap_mem(1)
//    printf("stack addr: %p\n", &heap_mem); //heap_mem(0), &heap_mem(1)
//    printf("stack addr: %p\n", &heap_mem1); //heap_mem(0), &heap_mem(1)
//    printf("stack addr: %p\n", &heap_mem2); //heap_mem(0), &heap_mem(1)
//    printf("stack addr: %p\n", &heap_mem3); //heap_mem(0), &heap_mem(1)
//    
//    printf("read only string addr: %p\n", str);
//    for(int i = 0 ;i < argc; 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;
//}

5.3.2 运行结果

输出结果------

bash 复制代码
$ ./a.out 
code addr: 0x40055d
init global addr: 0x601034
uninit global addr: 0x601040
heap addr: 0x1791010
heap addr: 0x1791030
heap addr: 0x1791050
heap addr: 0x1791070
test static addr: 0x601038
stack addr: 0x7ffd0f9a4368
stack addr: 0x7ffd0f9a4360
stack addr: 0x7ffd0f9a4358
stack addr: 0x7ffd0f9a4350
read only string addr: 0x400800
argv[0]: 0x7ffd0f9a4811
env[0]: 0x7ffd0f9a4819
env[1]: 0x7ffd0f9a482e
env[2]: 0x7ffd0f9a4845
env[3]: 0x7ffd0f9a4850
env[4]: 0x7ffd0f9a4860
env[5]: 0x7ffd0f9a486e

5.3.3 两个问题探究

进程存在,地址空间就必须一直存在。

5.3.3.1 问题1:char *s ="hello world";*s = 'H"为什么不可以修改?
5.3.3.2 问题2:static(静态)修饰局部变量:作用域不变,生命周期变成全局(?)

5.3 程序地址空间初识思维导图

如下图所示------


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾

【Linux进程(五)】Linux / Windows命令行参数与环境变量深度解析 | 附代码实验与配置技巧

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
in12345lllp2 小时前
IT运维AI化转型:系统性AI认证选择
运维·人工智能
阿钱真强道2 小时前
20 极物智能 knx-主机场景对接
linux·运维·服务器
海棠蚀omo2 小时前
万物互联的起点:走进 Linux 网络的心脏,开启一场从零开始的底层探索之旅
linux·网络
baivfhpwxf20232 小时前
C# 语言 SQL Server 批量更新
服务器·windows·c#
Godspeed Zhao2 小时前
自动驾驶中的传感器技术86——Sensor Fusion(9)
人工智能·机器学习·自动驾驶
咕咕嘎嘎10242 小时前
C++仿muduo库onethreadoneloop高并发服务器
服务器·网络·c++
Fortune_yangyang2 小时前
docker 搭建lnmp
运维·docker·容器
虾..2 小时前
Linux 信号发送和保存
linux·运维·服务器
说私域2 小时前
定制开发开源AI智能名片S2B2C商城小程序的产品经理职责与发展研究
人工智能·小程序·开源