进程地址空间

进程地址空间

进程地址空间的排布:堆栈相对而生

image-20240206195546914

这里的地址空间不是内存!
为何这样说呢?可以看以下的程序

#include <stdio.h>                                                             
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
int g_val=0;
int main()
{
  pid_t id =fork();
  if(id < 0)
  {perror("error!");}
  else if(id == 0)
  {  
    // child
    while(true)
    {
      g_val = 300;
      printf("child:g_val:%d, &g_val:%p, pid: %d\n", g_val, &g_val, getpid());
      sleep(1);
    }
  }
  else{
    // father
    while(true)
    {
      printf("father:g_val:%d, &g_val:%p, pid: %d\n", g_val, &g_val, getpid());
      sleep(1);
    }
  }
  return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同一个变量,不会出现两个值,所以这里的地址是虚拟地址

#include <stdlib.h>

int un_val;
int val = 1;

int main(int argc, char* argv[], char* env[])
{
  printf("text:%p\n", main);    // 代码区
  printf("un_val:%p\n", &un_val);
  printf("val:%p\n", val);
  int *p = (int*) malloc(sizeof(int));
  int *p2 = (int*) malloc(sizeof(int));
  printf("heap1:%p\n", p);
  printf("heap2:%p\n", p2);
  int s1 = 10;
  int s2 = 20;
  printf("stack1: %p", &s1);
  printf("stack2: %p", &s2);                   
}

image-20240206112830623

如果再在main函数里定义一个static变量,可以看到该变量的地址在全局区,所以static变量的本质就是将该变量开辟在全局区域

image-20240206190837259

字面常量const char*.char*,放在代码区

什么是进程地址空间(概念级别)

image-20240206195945994

如何理解区域划分

image-20240206205039674

深入理解进程地址空间(代码级别)

看task_struct的源码,可以看到有一个struct mm_struct *mm指针,其中mm_struct 就是地址空间,里面有各个区域的划分

所以地址空间就是一种内核数据结构

struct mm_struct {
    ...
    unsigned long start_code, end_code, start_data, end_data;
	unsigned long start_brk, brk, start_stack;
	unsigned long arg_start, arg_end, env_start, env_end;
    ...
}

image-20240206210120886

为什么同一个变量会有两个地址?

image-20240206210911572

为什么要有进程地址空间

  1. 凡是非法的访问或者映射,OS都能识别到
    (因为地址空间和页表是OS创建并且维护的,意味着凡是想要使用地址空间和页表进行映射,一定要在OS的监管下进行访问)
    ,并且终止这个进程,也便保护了物理内存中的所有合法数据,包括各个进程,以及内核的相关的有效数据

  2. 因为有地址空间的存在,页表映射的存在,我们的物理内存中,可以对未来的数据进行任意位置的加载

    物理内存的分配 就可以和 进程的管理做到没有关系,也就是内存管理模块 和 进程管理模块做到了解耦合
    我们在c/c++里malloc,new出来的空间是虚拟空间, 如果new出来后不立马使用,就会导致空间的浪费
    本质上,因为有地址空间的存在,所以上层在申请空间时,其实是在地址空间上申请的,物理内存可以甚至一个字节都不给你,
    而当你真正的对物理内存进行访址时(有os自动完成,用户和进程0感知),
    才执行内存的相关管理算法,帮你申请内存,构建页表映射关系,然后再让你进行内存的访问
    这种策略叫做延迟分配,用来提高整机的效率,这样,几乎内存的有效使用接近100%

  3. 物理内存在理论上可以任意位置加载,因此物理内存中几乎所有的数据和代码在内存中是乱序的,
    但是,因为页表的存在,可以将地址空间上的虚拟地址和物理地址进行映射,所以在进程视角上的内存分布是有序的
    所以①地址空间+页表的的存在,可以将内存分布有序化
    我们知道,地址空间是os给进程画的大饼,结合第2条,进程要访问物理内存中的数据和代码,可能目前并没有在物理内存中,同样的,
    也可以让不同的进程映射到不同的内存上,所以很容易实现进程的独立性
    进程的独立性可以通过地址空间+页表的方式实现
    结论:**因为有地址空间的存在,在32位系统下,每一个进程都认为自己有4gb有序的内存,通过页表映射到不同的区域,实现进程的独立性,
    每一个进程,不知道,也不需要知道其它进程的存在

再理解挂起

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 38
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值