一、linux的内存布局

1、32位模式下内存的经典布局​

linux内存管理策略,Glibc内存管理—ptmalloc内存分配策略(1)-编程之家图1

32位模式下内存经典布局

注:这种内存布局模式是linux内核2.6.7以前的默认内存布局形式

说明:(1)在32的机器上,loader将可执行文件的各个段次依次载入到从0x80048000(128M)位置开始的空间中。程序能够访问的最后地址是0xbfffffff(3G)的位置,3G以上的位置是给内核使用的,应用程序不能直接访问。

(2)内存布局从低地址到高地址依次为:txet段、data段、bss段、heap、mmap映射区、stack堆栈区。

(3)​heap和mmap是相对增长的,也就意味着heap只有1G的虚拟地址空间可供使用。​

(4)​stack区域不需要映射的,用户可以直接访问该区域。这也是利用堆栈溢出进行攻击的基础。

2、32位模式下内存的默认布局​

linux内存管理策略,Glibc内存管理—ptmalloc内存分配策略(1)-编程之家图2

32位模式下内存的默认布局

注:这种内存布局是linux内核2.6.7之后32位机器的默认内存布局方式。

说明:(1)这种内存布局方式加入了几个Random

offset的随机偏移,这样的话内存溢出的攻击就不会那么容易了。

(2)

​栈是自顶向下扩展的,但是栈是有边界的栈大小就有了限制(linux小t乃下可以使用ulimit

-s

命令进行查看其大小)。堆是自底向上扩展的,mmap映射区自顶向下扩展。故mmap和heap是相对扩展的,直至消耗尽虚拟地址空间中的剩余区域,这种结构便于C运行库使用mmap映射区和堆进行内存分配

3、​64位模式下内存的默认布局

linux内存管理策略,Glibc内存管理—ptmalloc内存分配策略(1)-编程之家图3

64位模式下内存的默认布局

说明:这种内存布局方式沿用的32位模式下内存的经典布局,但是栈和mmap的映射区域不再是从一个固定的地方开始,每次启动时的值都不一样。这样一来,使得使用缓冲区溢出攻击变得更加困难。

​二、操作系统内存分配的相关函数

1、总括​

heap和mmap映射区域是可以提供给用户程序使用的虚拟内存空间,获得该区域的内存的操作有:​

(1)对于heap操作,操作系统提供了brk()系统调用,c运行库提供了sbrk()库函数。

(2)对于mmap映射区的操作,操作系统提供了mmap()和munm()系统调用。

(3)linux内存管理的基本思想:内存延迟分配。即只有在真正访问一个地址的时候才建立这个地址的物理映射。linux内核在用户申请内存的时候,只是给它分配了一个虚拟地址,并没有分配实际的物理地址,只有当用户使用这块内存的时候,内核才会分配具体的物理地址给用户使用。

2、heap操作的相关函数​

(1)brk()是系统调用、sbrk()是库函数。c语言的动态内存分配基本函数是malloc(),在​linux上的实现是:malloc()函数调用库函数sbrk(),sbrk()的实质是调用brk()函数。brk()是一个简单的系统调用,只是简单的改变mm_struct结构体的成员变量brkd的值。

(2)函数原型:

#include

​​​

int brk(void *

addr);

void *

sbrk(intptr_t increment);

//当参数increment为0时,sbrk()返回的是进程当前的brk值,increment为正数时扩展brk值,当increment为负数时收缩brk值

(3)mm_struct结构中的成员变量

start_code

和 end_code 是进程代码段的起始和结束地址、

start_data

和 end_data 是进程数据段的起始和终止地址。

start_stack  是进程堆栈段的起始地址。

start_brk

是进程动态内存分配的起始地址(堆的起始地址)。

​brk 是进程动态内存分配当前的终止地址(堆的当前最后地址)。

​3、Mmap映射区域操作的相关函数

(1)mmap()函数将一个文件或者其他对象映射进内存。文件被映射到多个页上,如果文件大小不是所有页大小之和,最后一个页不被使用的空间将会清零。munmap执行相反的操作,删除特定地址区域的对象映射。

(2)函数原型

#include​

void * mmap(void * addr,size_t length,int

prot,int flags,int fd,off_t offset)

int munmap(void *addr,size_t

length);

参数:start — 映射区的开始地址。

length —

映射区的长度。

prot —

期望的内存保护标志。

​flags —

指定映射对象的类型,映射选项和映射页是否可以共享。

fd — 有效的文件描述符。

offset —

被映射对象内容的起点。​