我是靠谱客的博主 热心大树,最近开发中收集的这篇文章主要介绍Linux概念——进程地址空间,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Linux概念——进程地址空间

      • <1> 进程地址空间
      • Q1:什么是地址空间?
      • <2> 虚拟地址空间
      • Q2:为什么要有地址空间?
      • Q3: 地址空间时怎么工作的?
      • <3> 页表

<1> 进程地址空间

对于C语言学习,我们并不陌生这张图
在这里插入图片描述
我们编写一段C语言代码来验证上述图的准确性

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

int g_val = 100;
int g_unval;

int main(int argc, char* argv[], char* env[])
{
  //环境变量
  printf("env addr:%pn", env[0]);
  printf("env addr:%pn",env[1]);
  //命令行参数
  printf("argv addr:%pn",argv[0]);
  printf("argv addr:%pn",argv[argc-1]);
  char* mem = (char *)malloc(sizeof(char)*4);

  //栈
  printf("Stack addr:%pn",&mem);
  //堆
  printf("Heap addr:%pn",&mem);
  //未初始化数据
  printf("uninit addr:%pn",&g_unval);
  //初始化数据
  printf("init addr:%pn",&g_val);
  //正文代码
  printf("code addr:%pn",&main);

  return 0;
}

结果

在这里插入图片描述
可以看到对于程序中定义的变量打印出来的地址全部都一一对应了

Q1:什么是地址空间?

地址空间是对物理内存的一种虚拟化表示,在Linux内核中以结构体的形式划分为不同的区域。

<2> 虚拟地址空间

既然前面说到了进程空间是一种虚拟化表示,我们运行下面代码来验证进程地址空间

#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 
     printf("child[%d]: %d : %pn", getpid(), g_val, &g_val);
  }
  else
  { //parent
    printf("parent[%d]: %d : %pn", getpid(), g_val, &g_val);
  }
  sleep(1);
  return 0;
}

在这里插入图片描述
由结果可以看出,父进程的全局变量地址和子进程的全局变量地址相同,正好对应了进程空间地址那张图,那么我们稍作修改

#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 : %pn", getpid(), g_val, &g_val);
  }
  else
  { //parent
    sleep(3);
    printf("parent[%d]: %d : %pn", getpid(), g_val, &g_val);
  }
  sleep(1);
  return 0;
}

在这里插入图片描述
我们发现,父子进程,输出地址是一致的,但是变量内容不一样

能得出如下结论:

  • 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
  • 但地址值是一样的,说明该地址绝对不是物理地址
  • 在Linux地址下,这种地址叫做虚拟地址
  • 我们在用C/C++语言所看到的地址,全部都是虚拟地址物理地址,用户一概看不到,由OS统一管理

Q2:为什么要有地址空间?

  1. 如果没有地址空间,那么进程访问的地址都是物理地址,当一个进程的指针去读写另一个进程的地址时,出现野指针现象,导致别人的空间遭到破坏,从而违背了进程的独立性原则。
  2. 进程数据存放的位置时不连续的,因此访问难度较大,也增加了异常越界的概率。

Q3: 地址空间时怎么工作的?

  1. 既然地址空间时虚拟的,那么OS必须负责将 虚拟地址 转化成 物理地址 , 这中间就需要建立映射关系——页表来进行转换。
  2. 由操作系统去访问物理内存,人为干扰的进程非法行为将被禁止,堆内存起到了保护作用。

<3> 页表

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

最后

以上就是热心大树为你收集整理的Linux概念——进程地址空间的全部内容,希望文章能够帮你解决Linux概念——进程地址空间所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部