[LDD3速记]_内存分配
来源:互联网 发布:网络禁歌120首试听 编辑:程序博客网 时间:2024/05/13 06:15
一、kmalloc函数
原型:
#include <linux/slab.h>void *kmalloc(size_t size, int flags);
最终总是调用get_free_pages(GFP)实现
1. flags参数
常用的标志:
GFP_KERNEL:运行于进程上下文,可休眠以等待一个页面(休眠时内核把缓冲区的内容刷写到硬盘,或者从一用户进程换出内存,以获取一个内存页面)
GFP_ATOMIC:原子性分配,可在进程上下文之外被调用(如中断处理进程、tasklet以及内核定时器)
还有一些标志控制如何进行分配,可以上面的“或”起来使用:
__GFP_DMA:分配DMA区段的内存
__GFP_HIGHMEM:可位于高端内存(但是kmalloc不能分配高端内存)
Linux内核把内存分为三个区段:DMA内存、常规内存、高端内存
2. size参数
内核只能分配一些预定义的、固定大小的字节数组
kmalloc能处理的最小的内存块是32或64,最大不该超过128KB(为了具有完整的移植性)
二、后备高速缓存
驱动程序经常反复分配同一大小的内存块,为这些块增加某些特殊的内存池,这种形式的内存池称为后备高速缓存(lookasidecache)
内核的高速缓存管理器有时称为“slab分配器”,它实现的高速缓存具有kmem_cache_t类型,通过kmem_cache_create创建
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));
该函数创建一个高速缓存对象,可容纳任意数目的内存区域,由size决定,name保管一些信息以便追踪(可直接用字符串),offset为第一个对象的偏移量
flags标志:
SLAB_NO_REAP:保护高速缓存不被减少(系统寻找内存时)
SLAB_HWCACHE_ALIGN:要求所有数据对象跟高速缓存行(cache line)对齐
constructor、destructor:可选参数(不能只有destructor而没有constructor),前者用于初始化新分配的对象,后者用于释放对象
void *kmem_cache_alloc(kmem_cache_t *cache, int flags);/* 创建高速缓存对象后,可调用此函数从中分配内存对象,其中flags与kmalloc的相同 */void kmem_cache_free(kmem_cache_t *cache, const void *obj);/* 释放内存对象 */int kmem_cache_destroy(kmem_cache_t *cache);/* 释放高速缓存对象,需内存对象均归还才能成功,若失败->内存泄漏 */
可从/proc/slabinfo获得高速缓存的使用情况
三、get_free_page
分配大块内存,面向页,不产生内存碎片
get_zeroed_page(unsigned int flags);/* 返回新页面的指针,并清零 */__get_free_page(unsigned int flags);/* 返回新页面的指针,不清零 */__get_free_pages(unsigned int flags, unsigned int order);/* 分配若干页(物理连续),返回第一个字节的指针,不清零 */
其中flags与kmalloc的一样,order是页面数的以2为底的对数(log2 N),可以使用函数get_order()转换
void free_page(unsigned long addr);void free_pages(unsigned long addr, unsigned long order);/* 释放页面,第一个函数是一个宏,调用第二个函数 */
alloc_pages接口:
struct page *alloc_pages_node(int nid, unsigned int flags,unsigned int order);/* Linux页分配器核心代码 */struct page *alloc_pages(unsigned int flags, unsigned int order);struct page *alloc_page(unsigned int flags);/* 两个宏 */void __free_page(struct page *page);void __free_pages(struct page *page, unsigned int order);void free_hot_page(struct page *page);//高速缓存中的void free_cold_page(struct page *page);//高速缓存中的/* 释放 */
四、vmalloc函数
1 .特性
虚拟地址连续,但物理地址可能不连续
分配的内存使用起来效率不高,不鼓励使用
与kmalloc的差异:kmalloc返回的虚拟地址与物理内存是一一对应的(可能有PAGE_OFFSET偏移),而vmalloc的虚拟地址需建立页表进行映射,故当需要真正的物理地址时不应使用vmalloc
不能用于原子上下文,内部调用kmalloc(GFP_KERNEL),可能休眠
2. 接口
#include <linux/vmalloc.h>void *vmalloc(unsigned long size);//分配void vfree(void * addr);//释放/* 使用示例:create_module */void *ioremap(unsigned long offset, unsigned long size);void iounmap(void * addr);//释放/* 与vmalloc一样会建立页表,但不实际分配内存更多用于映射(物理的)PCI缓冲区地址到(虚拟的)内核空间返回的地址需用readb或其他I/O函数来访问,不应直接访问*/
五、获取大的、连续的缓冲区
方法:在引导时获得专用缓冲区
#include <linux/bootmem.h>void *alloc_bootmem(unsigned long size);void *alloc_bootmem_low(unsigned long size);void *alloc_bootmem_pages(unsigned long size);void *alloc_bootmem_low_pages(unsigned long size);/* _low版本防止分配高端内存(高端内存不能用于DMA操作) */void free_bootmem(unsigned long addr, unsigned long size);/* 注意:释放的部分页面不会返回给系统 */
- [LDD3速记]_内存分配
- [LDD3速记]_内核定时器
- [LDD3速记]_中断处理
- [LDD3速记]_内核的数据类型
- [LDD3速记]_与硬件通信(I/O端口和I/O内存)
- ldd3-内核内存分配
- LDD3读书笔记----分配内存
- [LDD3速记]_PCI驱动程序
- LDD3学习笔记(11):内存分配
- [LDD3速记]_per-CPU变量
- JACK_C#_内存分配
- LDD3源码分析之按页分配内存
- LDD3源码分析之按页分配内存
- LDD3读书笔记(第5章 内存分配)
- LDD3源码分析之按页分配内存
- LDD3源码分析之按页分配内存
- 分配内存_释放内存
- [LDD3速记]_tasklet、工作队列、共享队列
- ffmpeg函数介绍
- 利用昆虫的夜视机制开发新式摄像机
- 字符串匹配算法KMP
- 液晶常用接口“LVDS、TTL、RSDS、TMDS”技术原理介绍
- 关于音频数据求DB值的问题
- [LDD3速记]_内存分配
- 子进程分父进程时间片的问题
- android 动态加载jar
- iOS绘图-1
- Git笔记
- ffmpeg中的sws_scale算法性能测试
- iOS 验证邮箱是否正确
- tomcat下域名的配置,ROOT.xml的作用
- matlab 检验类型语句