虚拟地址空间:
程序中看到的地址并不是物理内存地址,而是由系统内核的内存管理系统管理后
看到的虚拟地址。
物理内存有自己的地址,操作系统会维护一张映射表,表里面是虚拟地址和物理地址的映射关系,每个进程都有一张自己的
映射表。
CPU中由一个MMU存储单元,负责虚拟地址和物理地址转换。
虚拟地址空间:就是一个虚拟地址范围,
32位操作系统有4G虚拟内存:范围0~3G-1 用户使用 3G~4G-1 内核使用
64位操作系统:用户:0x0000 0000 0000 0000 ~ 0x0000 ffff ffff ffff
内核:0xffff ffff ffff 0000 ~ 0xffff ffff ffff ffff
#include#include #include //初始化的常全局变量 const int const_g_a = 10; //初始化的全局变量 int g_a = 20; //未初始化的全局变量 int g_b; int main(int argc,char *argv[],char *envp[]) { //常静态局部变量 const static int const_static_a =30; //初始化的静态局部变量 static int static_a =40; //未初始化的静态局部变量 static int static_b; //常局部变量 const int const_a =50; //局部变量 int a =60; //未初始化的局部变量 int b; //堆区 int *p = malloc(sizeof(int)); //string char * s_a = "adf"; printf("----命令行参数和环境变量n"); printf("argv %pn",argv); printf("envp %pn",envp); printf(" --------栈区---------n"); printf("常局部变量 %pn",&const_a); printf("初始化的局部变量 %pn",&a); printf("未初始化的局部变量 %pn",&b); printf("----------堆区--------n"); printf("p %pn",p); printf("--------BSS-----------n"); printf("未初始化的全局变量 %pn",&g_b); printf("未初始化局部静态变量%pn",&static_b); printf("----------数据区--------n"); printf("初始化的全局变量 %pn",&g_a); printf("初始化的静态局部变量 %pn",&static_a); printf("----------代码区--------n"); printf("常全局变量 %pn",&const_g_a); printf("常静态局部 %pn",&const_static_a); printf("函数 main %pn",main); printf("string %pn",s_a); printf("%dn",getpid());//获取进程编号 getchar(); return 0; } ----命令行参数和环境变量 argv 0x7ffcc091d4f8 envp 0x7ffcc091d508 --------栈区--------- 常局部变量 0x7ffcc091d3ec 初始化的局部变量 0x7ffcc091d3f0 未初始化的局部变量 0x7ffcc091d3f4 ----------堆区-------- p 0x2506010 --------BSS----------- 未初始化的全局变量 0x601070 未初始化局部静态变量0x60106c ----------数据区-------- 初始化的全局变量 0x601060 初始化的静态局部变量 0x601064 ----------代码区-------- 常全局变量 0x400928 常静态局部 0x400b6c 函数 main 0x4006b6 string 0x40092c 81704
内存壁垒:系统为每个进程的用户空间维护一张属于该进程的内存映射表
记录虚拟内存到物理内存的对应关系,因此在不同进程间交换虚拟内存地址是毫无意义的
不同的进程通过系统调用访问的内核代码和数据是同一份
用户空间的内存映射表会随着进程的切换而切换,内核空间的内存映射表
内核空间的映射表则不需要随着进程切换而切换
段错误:访问内存映射表中找不到的地址,对只读内存(代码区的数据)进行写操作。



