linux内存管理之malloc、vmalloc、kmalloc的区别

1、kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存

2、kmalloc保证分配的内存在物理上是连续的,内存只有在要被DMA访问的时候才需要物理上连续,malloc和vmalloc保证的是在虚拟地址空间上的连续

3、kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大

4、vmalloc比kmalloc要慢。尽管在某些情况下才需要物理上连续的内存块,但是很多内核代码都用kmalloc来获得内存,而不是vmalloc。这主要是出于性能的考虑。vmalloc函数为了把物理内存上不连续的页转换为虚拟地址空间上连续的页,必须专门建立页表项。糟糕的是,通过vmalloc获得的页必须一个个地进行映射,因为它们物理上是不连续的,这就会导致比直接内存映射大得多的TLB抖动,vmalloc仅在不得已时才会用--典型的就是为了获得大块内存时。

malloc的实现原理

malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表(全局变量,一个内存块的链表指针)。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。
 malloc()在操作系统中的实现    在 C 程序中,多次使用malloc () 和 free()。不过,您可能没有用一些时间去思考它们在您的操作系统中是如何实现的。本节将向您展示 malloc 和 free 的一个最简化实现的代码,来帮助说明管理内存时都涉及到了哪些事情。   在大部分操作系统中,内存分配由以下两个简单的函数来处理:    void *malloc (long numbytes):该函数负责分配 numbytes 大小的内存,并返回指向第一个字节的指针。    void free(void
*firstbyte):如果给定一个由先前的 malloc 返回的指针,那么该函数会将分配的空间归还给进程的“空闲空间”。

malloc_init 将是初始化内存分配程序的函数。它要完成以下三件事:将分配程序标识为已经初始化,找到系统中最后一个有效内存地址,然后建立起指向我们管理的内存的指针。这三个变量都是全局变量:

如前所述,被映射的内存的边界(最后一个有效地址)常被称为系统中断点或者当前中断点。在很多 UNIX? 系统中,为了指出当前系统中断点,必须使用sbrk(0) 函数。 sbrk 根据参数中给出的字节数移动当前系统中断点,然后返回新的系统中断点。使用参数 0 只是返回当前中断点。这里是我们的 malloc 初始化代码,它将找到当前中断点并初始化我们的变量

现在,为了完全地管理内存,我们需要能够追踪要分配和回收哪些内存。在对内存块进行了 free 调用之后,我们需要做的是诸如将它们标记为未被使用的等事情, 并且, 在调用 malloc 时, 我们要能够定位未被使用的内存块。 因此, malloc返回的每块内存的起始处首先要有这个结构:

现在, 您可能会认为当程序调用 malloc 时这会引发问题 —— 它们如何知道这个结构?答案是它们不必知道;在返回指针之前,我们会将其移动到这个结构之后, 把它隐藏起来。 这使得返回的指针指向没有用于任何其他用途的内存。 那样,从调用程序的角度来看,它们所得到的全部是空闲的、开放的内存。然后,当通过 free() 将该指针传递回来时,我们只需要倒退几个内存字节就可以再次找到这个结构。在讨论分配内存之前,我们将先讨论释放,因为它更简单。为了释放内存,我们必须要做的惟一一件事情就是,获得我们给出的指针,回退
sizeof(structmem_control_block) 个字节,并将其标记为可用的。这里是对应的代码:

如您所见,在这个分配程序中,内存的释放使用了一个非常简单的机制,在固定时间内完成内存释放。分配内存稍微困难一些。我们主要使用连接的指针遍历内存来寻找开放的内存块。这里是代码:

这就是我们的内存管理器。现在,我们只需要构建它,并在程序中使用它即可.多次调用 malloc()后空闲内存被切成很多的小内存片段,这就使得用户在申请内存使用时,由于找不到足够大的内存空间,malloc()需要进行内存整理,使得函数的性能越来越低。聪明的程序员通过总是分配大小为 2 的幂的内存块,而最大限度地降低潜在的 malloc 性能丧失。也就是说,所分配的内存块大小为4 字节、8 字节、16
字节、18446744073709551616 字节,等等。这样做最大限度地减少了进入空闲链的怪异片段(各种尺寸的小片段都有)的数量。尽管看起来这好像浪费了空间,但也容易看出浪费的空间永远不会超过 50%。

时间: 2024-10-13 20:12:24

linux内存管理之malloc、vmalloc、kmalloc的区别的相关文章

从上到下看linux内存管理--glibc malloc

Rerfences Understanding glibc malloc anatomy-of-a-program-in-memory Linux堆内存管理深入分析(上) Linux堆内存管理深入分析(下) Data_segment 实验平台: x86_64 GNU/Linux Linux version 3.10.0 32 bit linux 虚拟内存布局 fig 1. 32bit linux 虚拟内存布局 fig 1展示了linux 32bit系统上虚拟内存布局,代码段(text segme

Linux内存管理机制简介

在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,区别于 Windows的内存管理. 主要特点是,无论物理内存有多大,Linux 都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能.而Windows 是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间.换句话说,Linux自身的预分配内存机制使得主机上的物理内存会全部被用上.每增加一

Linux内存管理 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4491368.html Linux内存管理 摘要:本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法.力求从外到内.水到渠成地引导网友分析Linux的内存管理与使用.在本章最后,我们给出一个内存映射的实例,帮助网友们理解内核内存管理与用户内存管理之间的关系,希望大家最终能驾驭Linux内存管理. 前言 内存管理一向是所有操作系统书

伙伴系统之伙伴系统概述--Linux内存管理(十四)

日期 内核版本 架构 作者 GitHub CSDN 2016-09-02 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 1 前景回顾 1.1 Linux内存管理的层次结构 Linux把物理内存划分为三个层次来管理 层次 描述 存储节点(Node) CPU被划分为多个节点(node), 内存则被分簇, 每个CPU对应一个本地物理内存, 即一个CPU-node对应一个内存簇bank,即每个内存簇被认为是一个节点 管理区(Zone)

linux内存管理-内核用户空间 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4491362.html 1,linux内存管理中几个重要的结构体和数组 page unsigned long flags 一组标志,也对页框所在的管理区进行编号 atomic_t _count 该页被引用的次数 atomic_t _mapcount 页框中页表项数目,如果没有则为-1 struct list_head lru 管理page忙碌/空闲链表(inactive_list/active_list)

转 Linux内存管理原理

Linux内存管理原理 在用户态,内核态逻辑地址专指下文说的线性偏移前的地址Linux内核虚拟3.伙伴算法和slab分配器 16个页面RAM因为最大连续内存大小为16个页面 页面最多16个页面,所以16/2order(0)bimap有8个bit位两个页框page1 与page2组成与两个页框page3 与page4组成,这两个块之间有一个bit位 order(1)bimap有4个bit位order(2)bimap有4个bit位的2个页面分配过程 当我们需要order(1)的空闲页面块时,orde

linux内存管理概述

其中介绍了虚拟内存的机制以及mmap系统调用的实现.mmap允许直接将设备内存映射到用户进程的地址空间中.物理内存的管理,包括缓存的分配及回收,请页机制,交换空间等. 1)交换模块(swap) 这个模块负责控制内存内容的换入换出,它通过替换机制,使得物理内存的页框(RAM页)中保留有效的逻辑页,即从主存中淘汰最近没被访问的逻辑页,保存近来访问过的逻辑页.该模块实现的源程序分别是: page_io.c的主要函数功能是读写交换文件. swap_state.c的主要函数功能是修改交换高速缓存(swap

Windows内存管理和linux内存管理

windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或者页面,然后把页式虚拟地址与内存地址建立一一对应的页表:并用相应的硬件地址变换机构来解决离散地址变换问题.页式管理采用请求调页或预调页技术来实现内外存存储器的统一管理.其优点是没有外碎片,每个内碎片不超过页的大小.缺点是,程序全部装入内存,要求有相应的硬件支持.例如地址变换机构缺页中断的产生和选择淘

伙伴系统之伙伴系统概述--Linux内存管理(十五)

在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Knowlton设计, 后来Knuth又进行了更深刻的描述. 伙伴系统是一个结合了2的方幂个分配器和空闲缓冲区合并计技术的内存分配方案, 其基本思想很简单. 内存被分成含有很多页面的大块, 每一块都是2个页面大小的方幂. 如果找不到想要的块, 一个大块会被分成两部分, 这两部分彼此就成为伙伴. 其中一半被用来分配, 而另