linux内存管理(中),匿名存储段映射

glibc 的内存分配使用了数据段和内存映射。实现malloc最经典的方法就是将数据段分为一系列大小为2的幂的块,返回最小的复合要求的块来满足请求。释放则只是简单的将这块区域标记为未使用。如果相邻的分区都是空闲的,他们会被合称一个更大的分区。如果堆的最顶端是空的,可以用brk来降低断电,使堆收缩,将内存返回给系统。

这种算法叫做伙伴内存算法,他的有点是告诉和简单,缺点是会产生两种类型的内存碎片。当使用的内存块大于请求的大小的时候则会产生内存碎片。这导致了内存的地使用率。外部碎片则是在空闲存储器合计起来足够满足一个请求,但是没有一个单独的空间块可以来处理这个请求时候发生的。这同样会导致内存利用不足,因为可能会分配一个更大的块,或者是分配失败。

内存管理伙伴算法:

https://blog.csdn.net/jy1075518049/article/details/43911183

因此对于比较大的分配,glibc并不使用堆么事创建一个匿名内存映射来满足要求。匿名存储器映射在第四章讨论的基于文件的映射十分相似,只是他并不是基于文件,所以我们称之为匿名,实际上一个匿名内存映射只是一块已经用0初始化大的内存块,以提供给用户使用。因为这种映射不是基于堆的所以不会产生内存碎片。

匿名映射的好处:

1.无需关心碎片。当程序不在需要这块内存的时候,只要撤销映射,这块内存就直接归还给系统了。

2.匿名存储映射的大小是可以调整的,可以设置权限,还能像普通的映射一样接收建议。

3.每个分配存在于独立的内存映射。没有必要再去管理一个全局的堆了


使用匿名内存映射与堆比起来有两个缺点:

每个存储器映射都是页面大小的整数倍。所以如果大小不是页面的整数倍会造成很大的空间浪费,对于比较小的分配来说空间的浪费会更加的显著,因为相对于使用的空间,浪费的空间会更大。

创建一个新的内存映射比从堆中返回内存的负载要打,因为使用堆几乎不涉及任何内核操作。越小的分配,这样的问题也就越明显。越小的分配,这样的问题也就越明显。

根据各自的优缺点来判断,glibc的malloc使用数据段来满足小的分配,而匿名内存映射则用来满足大的分配。两者的临界点是可以调的,并且会随着glibc版本的不同而发生变化。目前,临界点一般是128kb;比128kb小的分配由堆来实现,较大的由匿名存储映射来实现

####8.4.1创建匿名存储映射
或许你再某次分配想使用一个内存映射而不是堆,那么你可以使用mmap和unmmap来销毁

```
#include <sys/mman.h>
void* mmap(void* start,size_t length,int port,int flags,int fd,off_t offset);
int munmap(void* offset);
```

发布了93 篇原创文章 · 获赞 2 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_32783703/article/details/103763657