【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命令行参数与环境变量深度解析 | 附代码实验与配置技巧

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

相关推荐
风象南7 小时前
普通人用AI加持赚到的第一个100块
人工智能·后端
牛奶7 小时前
2026年大模型怎么选?前端人实用对比
前端·人工智能·ai编程
牛奶7 小时前
前端人为什么要学AI?
前端·人工智能·ai编程
罗西的思考10 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
冬奇Lab11 小时前
OpenClaw 源码精读(2):Channel & Routing——一条消息如何找到它的 Agent?
人工智能·开源·源码阅读
冬奇Lab11 小时前
一天一个开源项目(第38篇):Claude Code Telegram - 用 Telegram 远程用 Claude Code,随时随地聊项目
人工智能·开源·资讯
格砸12 小时前
从入门到辞职|从ChatGPT到OpenClaw,跟上智能时代的进化
前端·人工智能·后端
可观测性用观测云12 小时前
可观测性 4.0:教系统如何思考
人工智能
sunny86512 小时前
Claude Code 跨会话上下文恢复:从 8 次纠正到 0 次的工程实践
人工智能·开源·github
小笼包包仔13 小时前
OpenClaw 多Agent软件开发最佳实践指南
人工智能