Copyright: 该文章版权由潘云登所有。可在非商业目的下任意传播和复制。

对于商业目的下对本文的任何行为需经作者同意。


kmalloc

#include <linux/slab.h>

void *kmalloc(size_t size, int flags);

void kfree(const void *ptr);

使用kmalloc可以获得以字节为单位的一块内核内存,它不对所获取的内存空间清零。这个函数返回一个指向内存块的指针,其内存块至少要有size大小。所分配的内存区在物理上是连续的。在出错时,它返回NULL。因此,在调用kmalloc()后,必须检查返回的是不是NULL。由kmalloc分配的内存,使用kfree方法进行释放。

kmalloc的第一个参数是要分配块的大小,第二个参数是分配器标志。这个标志在<linux/gfp.h>文件中声明,可以分为三类:行为修饰符、区修饰符以及类型标识。行为修饰符表示内核应当如何分配所需的内存,主要有:

__GFP_WAIT    分配器可以休眠

__GFP_HIGH    分配器可以访问紧急事件缓冲池

__GFP_IO       分配器可以启动磁盘I/O

__GFP_FS       分配器可以启动文件系统I/O

区修饰符表示从哪里分配内存:可用于DMA的内存(__GFP_DMA)、常规内存以及高端内存(__GFP_HIGHMEM)。类型标志组合了行为修饰符和区修饰符,将各种可能用到的组合归纳为不同类型,简化了修饰符的使用。因此,最常使用的flags参数为GFP_KERNEL和GFP_ATOMIC。后者用在中断处理程序或其它运行于进程上下文之外的代码中,这时kmalloc方法不会休眠。

#include <linux/gfp.h>

#define GFP_KERNEL         (__GFP_WAIT | __GFP_IO | __GFP_FS)

#define GFP_ATOMIC        (__GFP_HIGH)

实际上,kmalloc是建立在后面介绍的后备高速缓存之上的。因此,内核只能分配一些预定义的、固定大小的字节数组。根据当前体系结构使用的页面大小,kmalloc能处理的最小内存块是32或者64。如果希望代码具有完整的可移植性,则不应该分配大于128KB的内存。

示例:

char *buf;

buf = kmalloc(BUF_SIZE, GFP_ATOMIC);

if (!buf)

/* 内存分配出错! */

kfree(buf);


后备高速缓存

分配和释放数据结构是所有内核中最普遍的操作之一。为了便于数据的频繁分配和回收,内核提供了后备高速缓存机制,称为“slab分配器”。slab分配器实现的高速缓存具有kmem_cache_t类型,可通过调用kmem_cache_create创建。

#include <linux/slab.h>

kmem_cache_t *kmem_cache_create(const char *name, size_t size,

size_t offset,

unsigned long flags,

void (*constructor)(void *, kmem_cache_t *, unsigned long flags),

void (*destructor)(void *, kmem_cache_t *, unsigned long flags));

参数name存放高速缓存的名字。size是高速缓存中每个元素的大小。offset是高速缓存中第一个对象的偏移,用来确保在页内进行特定的对齐,一般取0。flags是一个位掩码,用来控制高速缓存的行为。constructor和destructor为高速缓存的构造和析构函数,分别在新页追加到高速缓存和从高速缓存中删去页时调用,通常取NULL。kmem_cache_create在成功时返回一个指向所创建高速缓存的指针,否则,返回NULL。在创建高速缓存后,使用kmem_cache_alloc从中分配内存对象。释放一个内存对象时使用kmem_cache_free。要销毁一个高速缓存,则调用kmem_cache_destroy。

void *kmem_cache_alloc(kmem_cache_t *cache, int flags);

void kmem_cache_free(kmem_cache_t *cache, const void *obj);

int kmem_cache_destroy(kmem_cache_t *cache);

示例:

kmem_cache_t *task_struct_cachep;

/*创建高速缓存,SLAB_PANIC标志在分配失败时提醒slab层,

如果没有提供SLAB_PANIC 标志,必须自己检查返回值*/

task_struct_cachep = kmem_cache_create("task_struct",

sizeof(struct task_struct),

ARCH_MIN_TASKALIGN,

SLAB_PANIC,

NULL,

NULL);

/*分配内存对象*/

struct task_struct *tsk;

tsk = kmem_cache_alloc(task_struct_cachep, GFP_KERNEL);

if (!tsk)

return NULL;

/*释放内存对象*/

kmem_cache_free(task_struct_cachep, tsk);

/*撤销高速缓存*/

int err;

err = kmem_cache_destroy(task_struct_cachep);

if (err)

/*撤销高速缓存出错*/


分配页

如果模块需要分配大块的内存,使用面向页的分配技术会更好些。分配页面可以使用下面的函数:

#include <linux/gfp.h>

unsigned long get_zeroed_page(unsigned int gfp_mask);

unsigned long __get_free_page(unsigned int gfp_mask);

unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order);

它们返回内存区域第一个字节的指针。其中,get_zeroed_page将分配所得的页面清零。参数gfp_mask为分配器标志,与kmaloc中的一样。参数order是要分配的页面数的以2为底的对数。当用字节表示内存大小时,需要使用get_order函数进行转换,而不应该对页面大小进行任何假设,如:

#include <asm/page.h>

/*驱动程序需要16KB空间*/

/* get_order的参数必须是2的幂*/

int order = get_order(16*1024);

buf = get_free_pages(GFP_KERNEL, order);

当程序不再需要使用页面时,可以使用下列函数进行释放:

void free_page(unsigned long addr);

void free_pages(unsigned long addr, unsigned long order);

示例:

unsigned long page;

page = __get_free_pages(GFP_KERNEL, 3);

if (!page) {

/*没有足够的内存,你必须处理这种错误! */

return ENOMEM;

}

/* 'page'现在指向8个连续页中第1个页的地址*/

free_pages(page, 3);


vmalloc

#include <linux/vmalloc.h>

void * vmalloc(unsigned long size);

void vfree(void *addr);

vmalloc函数的工作方式类似于kmalloc,只不过前者分配的内存虚拟地址是连续的,而物理地址则无需连续。它通过分配非连续的物理内存块,再修改页表,把内存映射到逻辑地址空间的连续区域中。通过vmalloc获得的页必须一个一个地进行映射,效率不高,因此,只在不得已(一般是为了获得大块内存)时使用。vmalloc函数返回一个指针,指向逻辑上连续的一块内存区,其大小至少为size。在发生错误时,函数返回NULL。vmalloc可能睡眠,因此,不能从中断上下文中进行调用,也不能从其它不允许阻塞的情况下调用。要释放通过vmalloc所获得的内存,应使用vfree函数。

示例:

char *buf;

buf = vmalloc(16 * PAGE_SIZE); /*获得16页*/

if (!buf)

/*错误,不能分配内存*/

vfree(buf);

内存分配方法 kmalloc()、vmalloc()、__get_free_pages()的更多相关文章

  1. linux内存分配方法总结【转】

    转自:http://www.bkjia.com/Linuxjc/443717.html 内存映射结构: 1.32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有. 2.s ...

  2. C语言内存分配方法。

    当C程序运行在操作系统上时,操作系统会给每一个程序分配一定的栈空间. 堆为所有程序共有的,需要时需要申请访问. 一.栈 局部变量.函数一般在栈空间中. 运行时自动分配&自动回收:栈是自动管理的 ...

  3. C++的STL中vector内存分配方法的简单探索

    STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux  CentOS 5.2 1.代码 #include <vector> #include <stdio ...

  4. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  5. Linux内核中常见内存分配函数【转】

    转自:http://blog.csdn.net/wzhwho/article/details/4996510 1.      原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页 ...

  6. Linux内核中常见内存分配函数

    1.      原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系统中,用到了四级页表,如图2-1所示.四级页表分 ...

  7. C++STL内存管理方法(g++版)

    STL作为C++的经典作品,一直备受人们关注.本文主要介绍STL的内存管理策略. 早期的STL内存管理 第一次接触STL源码是看侯捷先生的<STL源码剖析>,此书通俗易懂,剖析透彻,是极佳 ...

  8. memcache内存分配机制

    memcached的内存分配没有用到c语言中自带的malloc函数,因为这个函数分配内存的时候效率很低,对于这种要求快速响应,对效率要求非常高的缓存软件来说非常不合适. memcached用的是自己的 ...

  9. 转: Linux C 动态内存分配 malloc及相关内容 .

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

随机推荐

  1. WPF-控件-层级控件-TreeView

    <?xml version="1.0" encoding="utf-8" ?> <Data xmlns=""> &l ...

  2. vs2010旗舰版后,运行调试一个项目时调试不了,提示的是:无法使用“pc”附加到应用程序“webdev.webserver40.exe(PID:2260”

    具体问题描述: vs2010旗舰版后,运行调试一个项目时调试不了,能编译,按ctrl+f5 可以运行,但是就是调试就不行,提示的是:无法使用“pc”附加到应用程序“webdev.webserver40 ...

  3. c#之反射总结

     1.了解什么事程序集 2.加载程序集 首先要加载需要加载的程序集,然后找到指定的类型,进而往下进行动态加载. 要加载的程序集中的内容: public class Class1:Person { pr ...

  4. android 中设置HttpURLConnection 超时并判断是否超时

    设置超时: URL url1 = new URL(url); HttpURLConnection conn = (HttpURLConnection) url1.openConnection(); c ...

  5. java,图片压缩,略缩图

    在网上找了两个图片的缩放类,在这里分享一下: package manager.util; import java.util.Calendar; import java.io.File; import ...

  6. shell find and rm

    按时间删除命令: 删除当前目录下30天以前的所有文件: find . -type f -ctime + -exec rm -fr {} \; 删除当前目录下30天以前的所有目录: find . -ty ...

  7. protocol buffer 整数序列化

    http://blog.csdn.net/csfreebird/article/details/7624807 varints用于正整数 (无符号整数) varints 是 一个很不错的技术.将一个整 ...

  8. tornado解析http body的过程分析

    tornado解析http body的过程分析 在最近写的一个RESTful API Server过程中,发现tornaod对解析POST BODY的内容有限制. 而在以前用web.py则没有这个限制 ...

  9. How to define Servlet filter order of execution using annotations

    If we define Servlet filters in web.xml, then the order of execution of the filters will be the same ...

  10. UNIX command Questions Answers asked in Interview

    UNIX or Linux operating system has become default Server operating system and for whichever programm ...