Linux —— 进程地址空间

Linux进程地址空间与虚拟地址解析

目录

一,进程地址空间

地址空间分布

虚拟地址


一,进程地址空间

        进程地址空间,会在进程的整个生命周期内存在,直到进程结束;地址空间本质上是进程看待内存的方式,抽象出来的概念,在内核中为struct mm_struct;区域的划分,即将线性地址空间划分成一个个的区域[start,end];其作用是可保护物理内存,不受进程的直接访问,可进行合法性校验;可让进程以同样的方式,来看待代码和数据;进程管理和内存管理是强耦合的,也可将进程管理和内存管理解耦;

地址空间分布

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

int g_unval;
int g_val = 100;

int main(int argc, char* argv[], char* env[])
{
    printf("code addr: %p\n", main);
    const char* p = "hello world";
    printf("read only: %p\n", p);
    printf("global val: %p\n", &g_val);
    printf("global unval: %p\n", &g_unval);
    char* q = (char*)malloc(10);
    printf("heap addr: %p\n", q);
    printf("stack addr: %p\n", &p);
    printf("stack addr: %p\n", &q);
    printf("args addr: %p\n", argv[0]);
    printf("args addr: %p\n", argv[argc-1]);
    printf("env addr: %p\n", env[0]);
    return 0;
}
[wz@192 Desktop]$ ./target 
code addr: 0x40057d
read only: 0x40073f
global val: 0x60103c
global unval: 0x601044
heap addr: 0x17c5010
stack addr: 0x7fff85cc9148
stack addr: 0x7fff85cc9140
args addr: 0x7fff85cca2cf
args addr: 0x7fff85cca2cf
env addr: 0x7fff85cca2d8

虚拟地址

#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)
  {
    printf("child[%d],g_val=%d,&g_val=%p\n", getpid(),g_val,&g_val);
  }
  else
  {
    printf("parent[%d],g_val=%d,&g_val=%p\n", getpid(),g_val,&g_val);
  }
  return 0;
}
//运行结果,父子进程中变量g_val地址一样;
parent[118812],g_val=0,&g_val=0x601050
child[118813],g_val=0,&g_val=0x601050
#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)
  {
    g_val = 100;
    printf("child[%d],g_val=%d,&g_val=%p\n", getpid(),g_val,&g_val);
  }
  else
  {
    sleep(3); //保证子进程先计算完;
    printf("parent[%d],g_val=%d,&g_val=%p\n", getpid(),g_val,&g_val);
  }
  return 0;
}
//运行结果,父子进程中变量g_val地址仍是一样,但值确不一样;
child[119390],g_val=100,&g_val=0x601058
parent[119389],g_val=0,&g_val=0x601058

由以上两个程序说明

  • 变量g_val值不一样,说明父子进程中此变量一定不是同一变量;
  • 变量g_val地址一样,说明父子进程中此地址一定不是物理地址;

在Linux中,此地址称为虚拟地址

  • C/C++中所看到的地址,均为虚拟地址;
  • 用户是看不到物理地址的,物理地址统一由OS管理;
  • OS负责将虚拟地址转化为物理地址;
//地址空间区域划分
struct mm_struct
{
    unsigned long code_start;//代码区
    unsigned long code_end;
    
    unsigned long init_start;//初始化区
    unsigned long init_end;
    
    unsigned long uninit_start;//未初始化区
    unsigned long uninit_end;
    
    unsigned long heap_start;//堆区
    unsigned long heap_end;
    
    unsigned long stack_start;//栈区
    unsigned long stack_end;
    //...等等
}

Linux内核代码

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值