程序的内存空间

一:内核空间和用户空间

Linux的虚拟地址空间范围是0~4G,linux内核将这4G空间分为两部分,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF)供内核使用,称为“内核空间”。而将较低的3G字节(从虚拟地址0X00000000到0xBFFFFFFFF)供各个进程使用,称为“用户空间”。因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间
每个进程的用户空间都是完全独立,互不相干,用户进程各自有不同的页表。而内核空间是有内核负责映射的,不随进程改变,是固定的。内核空间有自己对应的页表;
这里指的32位内核地址空间划分,64位内核地址空间是不同的
进程空间分布

1.1:内核空间

linux内核在启动的时候会打印出内核空间的布局图:
init/mian.c:
start_kernel->mm_init->mem_init

1
2
3
4
5
6
7
8
9
10
11
12
13
Memory: 996228K/1048576K available (9216K kernel code, 1381K rwdata, 2940K rodata, 1024K init, 397K bss, 44156K reserved, 8192K cma-reserved, 253952K highmem)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xf0800000 - 0xff800000 ( 240 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xf0000000 ( 768 MB)
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
[ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
[ 0.000000] .text : 0xc0008000 - 0xc0a00000 (10208 kB) //代码段
[ 0.000000] .init : 0xc0e00000 - 0xc0f00000 (1024 kB) //init段 包含了大部分模块的初始化数据
[ 0.000000] .data : 0xc0f00000 - 0xc1059518 (1382 kB) //数据段的起始和结束地址,保存大部分内核的变量
[ 0.000000] .bss : 0xc105b000 - 0xc10be54c ( 398 kB) //BSS段的开始和结束地址,包含初始化为0的所有静态全局变量
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1

内核空间

内核空间分为三部分:ZONE_DMA(16M),ZONE_NORMAL(16~896),ZONE_HIGMEM(896~1G),高端内存
内核地址空间分为物理内存映射区,虚拟内存分配区,高端页面映射区,专用页面映射区保留区
内核空间中存放的是内核代码和数据,而进程的用户空间中存放的是用户程序的代码和数据。不管是内核空间还是用户空间,它们都处于虚拟空间中,虽然内核空间占据了每个虚拟空间的最高1GB字节,但映射到物理内存却总是从最低(0X00000000),另外,使用虚拟地址可以很好的保护内核空间不被破坏,虚拟地址到物理地址转换过程中有操作系统和CPU共同完成
内核空间是持续存在的,并且在所有进程中都映射到同样的物理内存,内核代码和数据总是可寻址的,随时准备处理中断和系统调用。

1.2:用户空间分布

程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码。
初始化过的数据(Data):在程序运行初已经对变量进行初始化的数据
未初始化过的数据(BSS):在程序运行初未对变量进行初始化的数据
栈(Stack):存储局部,临时变量,函数调用时,存储函数的返回指针,用于控制函数的调用和返回。在程序块开始时自动分配内存,结束时自动释放内存,其操作方式类似于结构中的栈;
堆(Heap):存储动态内存分配,需要程序员手工分配,手工释放;

三:内存溢出,内存泄漏,内存越界,缓存区溢出,栈溢出

内存溢出:要求分配的内存超出了系统能给予的
内存越界:申请了一块内存,在使用这块的时候,超出了你申请的范围
缓冲区溢出:当计算机向缓冲区填充区内填充数据位数

参考资料:
linux用户空间与内核空间——高端内存详解
ARM架构内核启动分析-head.S(1.1).vmlinux.lds链接脚本分析