Linux——程序地址空间

我们先来看这样一段代码:

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
int g_val = 0;
 
int main()
{
 pid_t id = fork();
 if(id < 0){
 perror("fork");
 return 0;
 }
 else if(id == 0){ //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
 g_val=100;
 printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
 }else{ //parent
 sleep(3);
 printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
 }
 sleep(1);
 return 0;
}

在代码中的子进程部分我们对全局变量g_val进行了修改,这个时候我们跑一下代码,大家觉得输出结果会是什么?接下来我来颠覆一下大家的认知

cpp 复制代码
child[3046]: 100 : 0x80497e8
parent[3045]: 0 : 0x80497e8

上述的就是输出结果,大家是不是觉得很不可思议?明明地址一样,值却不一样,这好像有违我们日常训练时的思维。接下来我来给大家进行解答。

首先,通过以上的结果我可以先给大家说出几个结论:

1.变量内容不一样,所以父子进程输出的变量绝对不是同一个变量。

2.但地址值是一样的,说明,该地址绝对不是物理地址!

3.在Linux地址下,这种地址叫做 虚拟地址。

4.我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理,OS必须负责将虚拟地址转化成物理地址 。

那为什么我们平时没有什么感觉呢?那是因为我们平时练习的时候都是单线程的,而多线程考虑的问题,我们平时遇到的很少,所以就没有察觉。

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

上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了 不同的物理地址!

我来给没见过和不理解的同学来解释解释这张图的大致描述:

我们知道子进程是会继承(共享)父进程的数据的,我们的task_struct里存有g_val的虚拟地址,虚拟地址通过映射来找到对应的物理地址空间,如果我们不去修改数据,那么我们的子进程对应的数据也确实跟父进程一模一样,但是我们现在修改数据了,修改数据的时候,我们的物理空间会开辟出来一块存放你修改的值,这个值只影响你对应的这个子进程,不会影响你的父进程,所以页表上虽然虚拟地址是一样的,但是映射出来对应的物理空间却是不一样的,所以我们就看到了输出结果的情况。

相关推荐
树℡独3 小时前
ns-3仿真之应用层(五)
服务器·网络·tcp/ip·ns3
小小管写大大码3 小时前
如何让vscode变得更智能?vscode接入claude实现自动编程
运维·ide·vscode·自动化·编辑器·ai编程·腾讯云ai代码助手
嵩山小老虎3 小时前
Windows 10/11 安装 WSL2 并配置 VSCode 开发环境(C 语言 / Linux API 适用)
linux·windows·vscode
Fleshy数模4 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
zhang133830890754 小时前
CG-09H 超声波风速风向传感器 加热型 ABS材质 重量轻 没有机械部件
大数据·运维·网络·人工智能·自动化
a41324474 小时前
ubuntu 25 安装vllm
linux·服务器·ubuntu·vllm
Configure-Handler4 小时前
buildroot System configuration
java·服务器·数据库
津津有味道4 小时前
易语言TCP服务端接收刷卡数据并向客户端读卡器发送指令
服务器·网络协议·tcp·易语言
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.5 小时前
Keepalived VIP迁移邮件告警配置指南
运维·服务器·笔记
物联网软硬件开发-轨物科技5 小时前
【轨物洞见】告别“被动维修”!预测性运维如何重塑老旧电站的资产价值?
运维·人工智能