Linux 进程地址空间

发布于:2024-09-18 ⋅ 阅读:(16) ⋅ 点赞:(0)

在这里插入图片描述

进程地址空间


C/C++对空间的划分

在这里插入图片描述

  • 这个图中展示的内容是在内存吗?

    我们称这个区域为地址空间。

图示

在这里插入图片描述


#include<stdio.h>
#include<stdlib.h>

int val_1;//未初始化全局变量
int val_2=100;//已初始化全局变量

int main()
{
  printf("code address: %p\n",main);//代码区
  const char *str="hello world";//字符常量区
  printf("str address: %p\n",str);//为什么是str,str就是保存的字符串常量的起始地址。

  printf("val_2 address: %p\n",&val_2);
  printf("val_1 address: %p\n",&val_1);

  char * mem=(char *)malloc(100);//堆区
  printf("heap address: %p\n",mem);

  printf("stack address: %p\n",&str);//栈区,局部变量在栈区
}

  • 栈区的地址是向下增长,堆区的地址是向上增长。堆栈相对而升。

  • static 修饰的变量

    为什么用 static 修饰的变量,就不会随着函数调用而被释放?
    因为 static 修饰的局部变量,在编译时已经被编译到全局数据区了,所以才不会被释放。

  • 结论

    如果变量的地址是物理地址,不可能存在父子进程访问的变量地址相同但是值不同的现象。出现这样的现象称为线性地址或者虚拟地址。所以平时写得 C/C++用的指针,指针里面的地址,绝对都不是物理地址,而是称为虚拟地址。


地址空间

一个可执行程序有代码数据两部分,还会创建进程地址空间。每一个进程都有进程地址空间。

地址空间的概念

概念:所谓的进程地址空间,本质是一个描述进程可视范围的大小。地址空间内一定要存在各种区域划分,对线性地址进行 start 和 end 划分即可。地址空间本质是内核的一个数据结构对象,类似 PCB 一样,地址空间也是要被操作系统管理的:先描述,再组织。


主要组成部分


请添加图片描述

  • 页表
    K(键) V(值) 结构
    键值为虚拟地址,值为物理地址

    当程序运行时,就会根据页表中的虚拟地址来找到对应的物理地址。

  • 写时拷贝的本质:

    重新开辟空间,但是在这个过程中,左侧的虚拟地址是不变的,不影响虚拟地址;而是在物理内存中开辟了新空间,将更改的信息存储到这个空间中。所以就出现了虚拟地址相同而值不同的现象。


常见细节问题

  • 总线

    CPU 与内存之间的线称为:系统总线
    内存和外设之间的线称为:IO 总线
    在 32 为计算机中,有 32 位的地址和数据总线。每一根总线只有 0,1 的概念。一共有 2^32 种状态。2^32*1byte=4GB,所以一个 32 位系统最多能装载 4GB 的内存空间。

  • 地址空间究竟是什么?

    • 什么叫做地址空间?

      地址总线排列组合形成的地址范围[0,2^32),

    • 如何理解地址空间上的区域划分?

  • 为什么要有进程地址空间?

      1. 让所有进程以统一的视角看待内存结构
      1. 增加进程虚拟地址空间,可以让我们访问的内存的时候,增加一个转换的过程,在这个转换的过程中,可以对我们的寻址请求进行审查,所以一旦异常访问,我们直接拦截,该请求不会到达物理内存,保护物理内存。
      1. 因为有地址空间和页表的存在,可以将进程管理模块和内存管理模块进行解耦合。
  • 页表结构是一个映射表。cr3 寄存器保存的是页表的起始地址(物理地址),这个地址是物理地址

  • 怎么知道进程的代码数据在不在内存?

    操作系统对大文件可以实现分批加载

  • 惰性加载

    操作系统对进程的加载策略为惰性加载的方式,

  • 缺页中断

    在页表中有一列为对应的代码和数据是否已经被加载到内存,如果显示不在,操作系统会触发缺页中断,操作系统会重新申请内存。(写时拷贝就是一种缺页中断)

  • 进程被创建的时候,是先创建内核数据结构呢?还是先加载对应的可执行程序呢?

    先创建内核数据结构


在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到