Linuxの概念-プロセスアドレス空間

<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:%p\n", env[0]);
  printf("env addr:%p\n",env[1]);
  //命令行参数
  printf("argv addr:%p\n",argv[0]);
  printf("argv addr:%p\n",argv[argc-1]);
  char* mem = (char *)malloc(sizeof(char)*4);

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

  return 0;
}

結果

ここに画像の説明を挿入します
プログラムで定義された変数に対して出力されたすべてのアドレスが1対1で対応していることがわかります。

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 : %p\n", getpid(), g_val, &g_val);
  }
  else
  {
    
     //parent
    printf("parent[%d]: %d : %p\n", 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 : %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;
}

ここに画像の説明を挿入します
親プロセスと子プロセスの出力アドレスは同じですが、変数の内容が異なることがわかりました

次の結論を導き出すことができます。

  • 変数の内容が異なるため、親プロセスと子プロセスによって出力される変数は、間違いなく同じ変数ではありません。
  • ただし、アドレス値は同じであり、アドレスが物理アドレスではないこと示しています
  • Linuxアドレスでは、このようなアドレスは仮想アドレスと呼ばれます
  • C / C ++に表示されるアドレスは、すべて仮想アドレスです。物理アドレスはユーザーには見えず、OSによって管理されます

Q2:アドレス空間があるのはなぜですか?

  1. アドレス空間がない場合、プロセスがアクセスするアドレスはすべて物理アドレスです。あるプロセスのポインタが別のプロセスのアドレスを読み書きすると、ワイルドポインタの現象が発生し、他の人の空間が破壊されます。 、したがって、プロセスの独立性に違反します。原則として。
  2. プロセスデータが保存される場所は連続的ではないため、アクセスがより困難になり、異常な範囲外の可能性も高くなります。

Q3:アドレス空間はどのように機能しますか?

  1. アドレス空間は仮想であるため、OSは仮想アドレスを物理アドレスに変換する責任があり、変換のためにページテーブルの中央でマッピング関係確立する必要があります
  2. オペレーティングシステムが物理メモリにアクセスすることにより、人為的な干渉のプロセスが禁止され、ヒープメモリが保護的な役割を果たします。

<3>ページテーブル

ここに画像の説明を挿入します
上の写真は名前の問題について話すのに十分です。同じアドレスを持つ同じ変数は実際には同じ仮想アドレスですが、異なる物理アドレスにマップされているため、内容が異なります。

おすすめ

転載: blog.csdn.net/qq_40076022/article/details/114544984