文章目录

  • 前言
  • 一、简单理解地址空间
  • 二、虚拟地址
    • 现象解释
  • 三、三个问题搞懂地址空间
    • 1. 什么是地址空间?
    • 2. 为什么要有地址空间?
    • 3. 地址空间是如何工作的?
  • 四、一些补充

前言

在之前的学习中,我们只学习了图中的下半部分(用户空间),当时还并未涉及到操作系统。

我们写一段代码来验证一下这张图。

#include<stdio.h>
#include<stdlib.h>int g_val = 100; //初始化
int g_unval; //未初始化
int main(int argc, char* argv[], char* env[])
{   // 以main函数为代表,打印代码区printf("code addr : %p\n", main); // 初始化数据printf("val addr : %p\n", &g_val);// 未初始化数据printf("unval addr : %p\n", &g_unval);char* mem = (char*)malloc(10);// 堆printf("heap addr : %p\n", mem);// 栈:指针变量(函数内,局部变量)printf("stack addr : %p\n", &mem);// 第一个命令行参数printf("opt addr : %p\n", argv[0]);// 最后一个命令行参数printf("opt addr : %p\n", argv[argc - 1]);// 环境变量printf("env addr : %p\n", env[0]);
}

运行结果 ↓

按照之前的说法,在C程序地址空间当中,地址的增长方向是自底向上。分别是代码段、已初始化全局数据区、未初始化全局数据区、堆区、栈区、命令行参数、环境变量。

其中,堆栈相对而生。栈向地址减小方向生长,堆向地址增大方向生长。堆栈之间的区域称为共享区。

再往上,叫做内核空间。

有两个小细节:
1、代码段不是从0号地址开始的,它有一个确定的地址。
2、共享区里一般放的是动态库,共享内存等。

这是以前的说法,是不准确的。
本文将详细介绍对于地址空间的认知。

首先要纠正的是,之前的程序地址空间应该叫做,进程地址空间

一、简单理解地址空间

我们知道猫咪是具有领地意识的,那么,是不是这片领地,猫咪随时都在使用呢? 不是的。
它只是限定了一片区域,属于它自身的活动范围。

所谓进程(猫咪)的地址空间(活动范围),进程不是随时随地使用这个地址空间内所有的资源。

【第一层理解】地址空间的作用:仅仅限定了一块内存空间,属于当前进程的一段活动范围,并不代表这个进程把所有资源都占有了。

二、虚拟地址

我们先来看一段代码

#include<stdio.h>
#include<unistd.h>
int g_val = 100;int main()
{pid_t id = fork();if(id == 0){//parentg_val = 1000;while (1){printf("g_val:%d, addr : %p  child \n", g_val, &g_val);sleep(1);}}else if (id > 0){//childwhile(1){sleep(3);printf("g_val:%d, addr : %p  father \n", g_val, &g_val);sleep(1);}}else{//error}
}

fork之后,父子进程谁先运行是由调度器决定的(随机的)。
让子进程先运行,修改全局变量g_val的值,观察现象。

在Linux中的运行结果是这样的。

我们发现,父进程打印的g_val依然是100。同时,父子进程打印的地址是一样的!
内存中的同一个地址,被不同的进程读取,打出来的值却完全不一样。
这是不可能发生的。

【第二层理解】所以,我们可以知道——地址空间绝对不是物理内存

进程和物理内存之间还存在一个虚拟层,叫做进程地址空间。

它其实是一种可被父进程指向的数据结构,父进程能看到的所有的内存的现象(或者叫布局情况)是被地址空间所解释的。而这部分区域可以在物理内存的任意区域被映射,此时就可以通过进程地址空间的内容访问物理内存中被映射的部分。

我们运用语言在屏幕上打印出来的地址其实都叫做“虚拟地址”。

从上面的例子,可以得出结论:
这里的地址,绝对不是物理地址,而是叫做虚拟地址。父子进程访问的数据,绝对被保存到了不同的物理内存中。
(只有物理内存有保存数据的能力,所谓的地址空间它仅仅是一种区域的划分。)


现象解释

为什么同样的地址,呈现的却是不一样的内容?

在创建子进程且子进程没有改写全局变量时,因为没有写入,只是读取,操作系统本着不浪费空间的目的,父子进程默认共享这段空间。
进程的运行是具有独立性的。体现在数据层面上先进行独立!

一旦!有任意一方,对数据进行了修改,父子进程就要进行数据的独立。单独给修改数据的这一方重新开了一块空间,重新构建一种映射关系。

在整个操作过程中,父进程是没有受任何影响的,且对子进程来说,只影响了子进程物理内存单独开辟的空间。它本身的虚拟地址是没有发生变化的,变的只是虚拟地址到物理地址的映射关系。

简单来说就是,
二者虚拟地址相同,但被映射到了不同的物理内存处。所以打出来的值也是不同的!

【第三层理解】地址空间是对物理内存的一种虚拟化表示。
进程只能看到虚拟地址,操作系统会帮我们把虚拟地址转化为物理地址。

进程的地址空间是内存吗?不是,给进程看到的永远都是虚拟地址,把物理内存保护起来。

三、三个问题搞懂地址空间

1. 什么是地址空间?

  • 本质是描述进程所占有空间的一张表,而它在操作系统内核当中,就是一个数据结构,这个数据结构,将我们的内存划分成了若干种区域,分别对应我们学过的那些区域。

每个进程都有一个进程的地址空间,系统中可能存在多个进程,每个进程透过地址空间访问内存,所以,系统中一定存在多个地址空间。所以,地址空间也要被管理起来。

只要是管理,就要先描述,再组织。

  • 先描述:

地址空间本质就是一个数据结构,
在Linux当中,叫做struct mm_struct(linux内核当中的地址空间结构体)
它包含了一些区域信息,能够实现区域划分。

struct mm_struct
{//划分区域Unsigned long code_start;Unsigned long code_end;Unsigned long init_data_start;Unsigned long init_data_end;Unsigned long uninit_start;Unsigned long uninit_end;Unsigned long head_start;Unsigned long head_end;....
}

申请空间的本质是:向内存索要空间,得到物理地址。然后在特定区域申请没有被使用的虚拟地址,建立映射关系,返回虚拟地址即可。

  • 再组织:

进程的PCB(task_struct)里有指向mm_struct的指针。
mm_struct相当于一张进程的执行地图。
我们知道一个进程 = PCB + 代码数据
因此,就把进程的PCB和mm_struct关联起来了。

2. 为什么要有地址空间?

假设如果没有地址空间,那么进程访问的地址都是物理地址。
当发生非法操作或异常的情况时,有可能就破坏其他空间的代码或数据。同时,也大概率会存在一个进程的数据存放的内存位置,是不连续的(代码和数据不连续)。

会导致

  1. 访问特别不方便
  2. 增加了异常越界的概率

为修正这些问题,计算机设计者想到了给每个进程创建一个虚拟地址空间。

解决了问题

  1. 保护物理内存:一个进程只会映射自己的数据,如果越界访问别人的空间,那么在页表当中是查找不到这种映射关系的,操作系统直接进行终止。也就是,只要进入内存访问了,一定是经过页表合法转化过来的。
  2. 页表中有相关的权限管理。可以通过页表的结构来限制一个进程对物理内存空间的访问。
  3. 转换的过程是操作系统做的。从最初的由用户去直接访问物理内存,改成了由操作帮我们访问,那么进程做的任何非法操作,操作系统可识别到。
  4. 同时做了空间连续化处理,方便使用。让我们的地址信息以连续的形式暴露给用户。

3. 地址空间是如何工作的?

地址空间上所呈现暴露给上层的所有的地址都叫做虚拟地址,而实际进程访问时,要通过页表映射转换到物理内存,然后拿到对应的代码和数据。

四、一些补充

通过认识地址空间,我们可以再次清晰进程!

  • 进程从硬盘加载到内存,操作系统为其创建task_struct 和 mm_struct 并且用指针把二者关联起来。
    然后,虚拟地址(mm_struct)通过页表和物理内存建立一种关系。

补充PCB中的内容分类说明:

内存指针:进程的pcb中包含了可以帮我们找到它代码和数据的指针信息。

程序计数器:保存当前正在执行指令的下一条指令的地址。

上下文数据:一个进程在CPU上运行会产生各种临时数据(就叫做当前进程的上下文),CPU内部保存数据的区域只有一份。
当进程切换时:时间片到了,或者有更高优先级的进程过来时,当前进程要发生切换,切换时要进行上下文保护;重新恢复回来时,要进行上下文恢复。保证这个进程能够接着上次被中断的位置继续运行。

进程地址空间(虚拟地址 | 物理内存)相关推荐

  1. [入门篇]用史上最生动的方式让你一篇博客搞懂Linux进程地址空间,包看包懂!

    目录 0.前言 1.初始程序的地址空间划分 1.1程序地址空间图解 1.2程序地址空间区域划分验证 1.3 程序地址空间小补充 1.4 引入进程地址空间 *2. 两个生动的例子理解进程地址空间 2.1 ...

  2. 两个不同的进程 虚拟地址相同_Linux的进程地址空间[一]

    所谓进程地址空间(process address space),就是从进程的视角看到的地址空间,是进程运行时所用到的虚拟地址的集合. 32位系统的进程地址空间 以IA-32处理器为例,其虚拟地址为32 ...

  3. Linux操作系统~什么是虚拟地址?深度剖析进程地址空间

    目录 1.所以进程的地址空间是什么呢? 2.mm_struct内部有什么? 3.虚拟地址空间与物理内存如何关联 页表 4.为什么设计这样一个进程地址空间,不让程序直接访问内存 Q:为什么子进程修改值以 ...

  4. Linux 内存管理 详解(虚拟内存、物理内存,进程地址空间)

    Linux -操作系统内存管理 存储系统 存储器的层次结构 Linux的内存管理 物理内存 物理内存管理 虚拟内存 虚拟地址空间 (写时拷贝) 和物理地址映射关系 页表 虚拟内存优缺点 「在 4GB ...

  5. 【Linux进程概念——下】验证进程地址空间的基本排布 | 理解进程地址空间 | 进程地址空间如何映射至物理内存(页表的引出) | 为什么要存在进程地址空间 | Linux2.6内核进程调度队列

    文章目录 [写在前面] 一.回顾与纠正 二. 验证进程地址空间的基本排布 三. 什么是进程地址空间

  6. linux 进程 地址空间 内存分布 简介

    目录 一 进程空间分布概述 二 内核空间和用户空间 三 进程内存布局 栈 内存映射段 堆 BBS和数据段 C语言程序实例 栈与堆的区别 一 进程空间分布概述 对于一个进程,其空间分布如下图所示: 程序 ...

  7. Linux进程地址空间学习总结

    Linux内核--内核地址空间分布和进程地址空间 http://www.cnblogs.com/bizhu/archive/2012/10/09/2717303.html 内核地址空间分布 直接映射区 ...

  8. Linux进程地址空间与进程内存布局详解,内核空间与用户空间

    Linux进程地址空间与进程内存布局详解 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码. 初始化过的数据(Data):在程序运行初已经对变量进行初始化的数据. 未初始化过的数据( ...

  9. linux 进程地址空间的一步步探究

    我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间. 那虚拟内存空间 ...

最新文章

  1. 转:ECharts图表组件之简单关系图:如何轻松实现另类站点地图且扩展节点属性实现点击节点页面跳转...
  2. Python time 100 天以后的日期
  3. jQuery获取元素内容
  4. LCD驱动移植(二)
  5. anaconda管理环境
  6. springboot自动配置_揭秘SpringBoot自动化配置
  7. HDU 3507 Print Article(单调队列)
  8. Netty源码分析第3章(客户端接入流程)----第1节: 初始化NioSockectChannelConfig
  9. Apache HBase 最新发布2.0.4 ,分布式数据库
  10. x64 盗版PCHunter
  11. usb转232串口线驱动android,prolific usb转串口驱动下载
  12. 计算机更新bios,GIGABYTE How to Reflash VGA BIOS
  13. java一个字符几个字节_Java 语言中一个字符占几个字节?
  14. vue实现浏览器桌面通知
  15. 前端 pdf 预览功能
  16. 又一批大学生毕业了,献上天津大学校园里的励志标语
  17. 运营——线上引流9大方法
  18. 数据治理:数据治理框架和标准
  19. js加密变量_Android上的Cloudbuild —使用加密的环境变量
  20. bWAPP中利用反射型xss获取cookie

热门文章

  1. Python入门程序练习题-温度转换
  2. 第四章 CSS入门 A卷
  3. VS1003音频解码芯片MP3播放器实现的问题-转载
  4. 使用php描述快速排序算法,PHP描述冒泡排序和快速排序算法
  5. [JavaWeb]—前端篇
  6. 小孩子教育不好产生如此严重的苦果
  7. 《青春依然,再见理想——献给学弟学妹》华中科技大学大四学生的万言忏悔书
  8. Adblock plus 过滤规则
  9. BZOJ3572 [HNOI2014]世界树
  10. IDE之KEIL declared implicitly 警告问题