目录
一,进程地址空间
进程地址空间,会在进程的整个生命周期内存在,直到进程结束;地址空间本质上是进程看待内存的方式,抽象出来的概念,在内核中为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内核代码
Linux进程地址空间与虚拟地址解析

1235

被折叠的 条评论
为什么被折叠?



