linux物理内存管理概述

简介: 随着用户程序的执行和结束,系统不断的为其进行分配与回收物理页面,这必然会产生大量的碎片,这些碎片被分成了两类:内部碎片与外部碎片。如下图:那么接下去我们要为程序分配一个3个连续的物理页面显然不可行了,虽然我们实际的物理内存中存在着3个物理页面这么大的空间,这些不连续的物理页面就成为了外部碎片。
随着用户程序的执行和结束,系统不断的为其进行分配与回收物理页面,这必然会产生大量的碎片,这些碎片被分成了两类:内部碎片与外部碎片。如下图:
img_6405b724406974216954acf9111e51a1.png
那么接下去我们要为程序分配一个3个连续的物理页面显然不可行了,虽然我们实际的物理内存中存在着3个物理页面这么大的空间,这些不连续的物理页面就成为了外部碎片。在linux系统中采用了伙伴算法来解决这个外部碎片的问题。在内核中有一个free_area这个结构体(include/linux/mmzone.h),它表示了内存中的空闲物理页面。结构体代码如下:

点击(此处)折叠或打开

  1. struct free_area{
  2.    struct list_head free_list[MIGRATE_TYPES];
  3.    unsigned long nr_free;
  4. };
对于伙伴算法中的伙伴是有条件的,即:
1)、两个快的大小相同;
2)、两个块的物理地址连续。
img_6195d9e482d8304779ec11ca00e199f2.png
下面我们结合上面这张图来说明该算法的工作原理。
假设要求分配的块的大小为128个页面。该算法先在块大小为128个页面的链表中查找,看是否有这样一个空闲块。如果有,就直接分配;如果没有,该算法会查找下一个更大的块,具体地说,就是在块大小为256个页面的链表中查找一个空闲块。如果存在这个空闲块,内核就把256个页面分为两等份,一份分配出去,另外一份插入到块大小为128的链表中。如果在块大小为256的链表中也没有找到空闲页块,就继续找更大的块,即512个页面的块。如果存在内核就从512分出128个页面满足请求,然后从384个页面中取出256个页面插入到大小256的链表中。然后把剩余的128个页面插入到大小为128个页面的链表中。如果512也没找到,那就继续向上找,一直找不到则算法放弃分配,并发出出错信号。
以上过程的逆过程就是块的释放过程。算法把满足伙伴条件的两个块合并为一个块,该算法是个迭代算法,如果合并后的块还可以跟相邻的块进行合并,那么该算法就继续合并。

slab机制:
伙伴算法也有不足,它不能解决内部碎片的问题,为了解决这个问题,内核又引入了slab机制,它主要是为了减少伙伴算法的调用次数。slab分配器为每个对象都建立了一个高速缓存,内核对这个对象的分配和释放都是在这个缓存中实现的。
img_f476ea9486dc68dd71c9d1500e50e10f.png
比如task_struct这个结构,在每次创建进程都会为这个结构体分配空间,在进程销毁后又回收这部分空间,那么内核就为其建立一个专用的缓冲区,而task_struct就是如上图所示的对象。每个高速缓冲区在内核中都是由kmem_cache这个结构表示的,每个slab都处于三种状态之一:满、部分满、空。
下面是一个slab分配实例,就用刚才提高到了的task_struct这个结构举例:代码在kernel/fork.c中。
首先,内核用一个全局变量存放指向task_struct高速缓冲区的指针:
struct kmem_cache *task_struct_cachep;
task_struct_cachep = kmen_cache("task_struct",sizeof(struct task_struct),
                                                          ARCH_MIN_TASKALIGN,
                                                          SLAB_PANIC|SLAB_NOTRACK,NULL);
这样就创建了一个名为task_struct的高速缓存,存放的数据类型为struct task_struct的对象。
在创建进程时,将会调用以下内容(dup_task_struct()中完成):
struct task_struct *tsk;
tsk = kmen_cache_alloc(task_struct_cachep,GFP_KERNEL);
if(!tsk)
    return NULL;
这些函数分配的都是专用缓冲区。但是当一个数据结构使用的不频繁,或者其大小不足一个页面时就没有必要给其分配专用缓冲区,而是通过kmalloc()或者数据结构大小接近一个页面时使用__get_free_pages()分配。这些分配的就是在通用缓冲区的分配。

相关文章
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
912 17
|
10月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
892 0
Linux内存问题排查命令详解
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
2811 6
|
缓存 Linux 数据安全/隐私保护
Linux环境下如何通过手动调用drop_caches命令释放内存
总的来说,记录住“drop_caches” 命令并理解其含义,可以让你在日常使用Linux的过程中更加娴熟和自如。
1969 23
|
12月前
|
监控 Linux 开发者
理解Linux操作系统内核中物理设备驱动(phy driver)的功能。
综合来看,物理设备驱动在Linux系统中的作用是至关重要的,它通过与硬件设备的紧密配合,为上层应用提供稳定可靠的通信基础设施。开发一款优秀的物理设备驱动需要开发者具备深厚的硬件知识、熟练的编程技能以及对Linux内核架构的深入理解,以确保驱动程序能在不同的硬件平台和网络条件下都能提供最优的性能。
590 0
|
监控 Linux Python
Linux系统资源管理:多角度查看内存使用情况。
要知道,透过内存管理的窗口,我们可以洞察到Linux系统运行的真实身姿,如同解剖学家透过微观镜,洞察生命的奥秘。记住,不要惧怕那些高深的命令和参数,他们只是你掌握系统"魔法棒"的钥匙,熟练掌握后,你就可以骄傲地说:Linux,我来了!
504 27
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
594 48
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
1475 59
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
3348 58
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
1009 58