进程虚拟地址空间内存划分和布局
对于任何的编程语言,产生的两种东西无非就是指令和数据。
比如在Windows上的xxx.exe文件,这个文件在磁盘上放着,运行的时候要加载到内存上去,当然不可能直接加载到物理内存上的。在x86体系32位的Linux系统上,系统会给当前进程分配一个2^32(4G)大小的一块空间,叫做进程的虚拟地址空间。
什么叫做虚拟地址空间?
有这么四句话很有名
1 | 它存在,你能看得见,它是物理的 |
进程虚拟地址空间
从地址0x00000000开始到0x08048000这块区域是不能访问的
1 | char *p=nullptr; |
接下来从0x08048000开始,存放的是.text段(指令存放的位置)。.rodata段(只读数据段)例如char *p=”hello world”; *p=’a‘,这个是不允许的。这两个段都是只能读不能写的。
接下来是.data段和.bss段,.data段存放的是初始化的并且初始化不为0的,.bss段存放的是未初始化和初始化为0的数据。
接下来是.heap堆区。刚开始是空的,只有调用new或者malloc才会有空间。
接下来是加载共享库,*.dll *so。
接下来是stack区,存放局部变量,不过栈区从下往上进行增长的。而堆是从高地址到低地址进行的。
接下来是命令行参数和环境变量。
上述存在于0x08048000到0xc0000000这3G的用户空间中。
下面还有1G的空间是内核空间,主要是这几种
1 | ZONE_DMA |
看看下面这些代码
1 | int gdata1=10;//data段 |
每一个进程的用户空间的私有的,内核空间是共有的。