内存分配方法 kmalloc()、vmalloc()、__get_free_pages()
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()的更多相关文章
- linux内存分配方法总结【转】
转自:http://www.bkjia.com/Linuxjc/443717.html 内存映射结构: 1.32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有. 2.s ...
- C语言内存分配方法。
当C程序运行在操作系统上时,操作系统会给每一个程序分配一定的栈空间. 堆为所有程序共有的,需要时需要申请访问. 一.栈 局部变量.函数一般在栈空间中. 运行时自动分配&自动回收:栈是自动管理的 ...
- C++的STL中vector内存分配方法的简单探索
STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux CentOS 5.2 1.代码 #include <vector> #include <stdio ...
- Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法
Investigating Your RAM Usage In this document Interpreting Log Messages 内存分析日志中各消息的含 ...
- Linux内核中常见内存分配函数【转】
转自:http://blog.csdn.net/wzhwho/article/details/4996510 1. 原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页 ...
- Linux内核中常见内存分配函数
1. 原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系统中,用到了四级页表,如图2-1所示.四级页表分 ...
- C++STL内存管理方法(g++版)
STL作为C++的经典作品,一直备受人们关注.本文主要介绍STL的内存管理策略. 早期的STL内存管理 第一次接触STL源码是看侯捷先生的<STL源码剖析>,此书通俗易懂,剖析透彻,是极佳 ...
- memcache内存分配机制
memcached的内存分配没有用到c语言中自带的malloc函数,因为这个函数分配内存的时候效率很低,对于这种要求快速响应,对效率要求非常高的缓存软件来说非常不合适. memcached用的是自己的 ...
- 转: Linux C 动态内存分配 malloc及相关内容 .
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
随机推荐
- 人工智能起步-反向回馈神经网路算法(BP算法)
人工智能分为强人工,弱人工. 弱人工智能就包括我们常用的语音识别,图像识别等,或者为了某一个固定目标实现的人工算法,如:下围棋,游戏的AI,聊天机器人,阿尔法狗等. 强人工智能目前只是一个幻想,就是自 ...
- 一个简单的脚本让你的ubuntu14.04记忆屏幕亮度
小弟献丑,发个没技术含量的.本人电脑是联想y400,无论是安装32位的ubuntu还是64位的ubuntu,无论是13.04还是现在的 14.04开发者版本,都无法让我的小y实现记忆屏幕亮度这个简单的 ...
- Palindrome Partitioning
Palindrome Partitioning Given a string s, partition s such that every substring of the partition is ...
- 动画(Animation) 之 (闪烁、左右摇摆、上下晃动等效果)
左右晃动的效果: (这边显示没那么流畅) 一.续播 (不知道取什么名字好,就是先播放动画A, 接着播放动画B) 有两种方式. 第一种,分别动画两个动画,A和B, 然后先播放动画A,设置A 的 Ani ...
- Video Toolbox:读写解码回调函数CVImageBufferRef的YUV图像
本文档基于H.264的解码,介绍读写Video Toolbox解码回调函数参数CVImageBufferRef中的YUV或RGB数据的方法,并给出CVImageBufferRef生成灰度图代码.方便调 ...
- c语言编程之栈(链表实现)
用链表实现栈,完成了出栈入栈功能. #include"stdio.h" typedef int element; //define a struct descirbe a stac ...
- .NET4安装总进度一直不动的解决办法
在安装.NET4时遇到上面的进度在动,而安装进度一直停在0,解决办法: 禁止并关闭Window Update服务,重新运行安装程序. 关闭服务:控制面板->管理工具->服务->Win ...
- asp.net 中插入数据到access
这样报语法错误: insert into Menu_wx(userid,menutype,MenuID,menuname,MenuTitle,Url,Key,OrderValue,State) val ...
- java多线程为什么要用while而不是if
对于java多线程的wait()方法,我们在jdk1.6的说明文档里可以看到这样一段话 从上面的截图,我们可以看出,在使用wait方法时,需要使用while循环来判断条件十分满足,而不是if,那么我们 ...
- DIV+CSS高手必知的15个CSS常识
1.不要使用过小的图片做背景平铺.这就是为何很多人都不用 1px 的原因,这才知晓.宽高 1px 的图片平铺出一个宽高 200px 的区域,需要 200*200=40, 000 次,占用资源. 2.无 ...