Linux内外存访问
内存分配
malloc()和free()
在C语言中,经常会遇到malloc()和free()这两个函数冤家。
malloc()函数用来进行内存的分配。
free()函数用来释放内存。
kmalloc()和kfree()
kmalloc()函数用于内核态的内存分配。kmalloc()函数在物理内存中为程序分配一个连续的存储空间。这个存储空间的数据不会被清零,也就是保存内存中原有的数据。
void *kmalloc(size_t size, gfp_t flags)
/* size参数 最小为32字节 最大为128KB */
/* flags参数 GFP_KERNEL 内存分配时最常用的方法,当内存不足时,可能会引起休眠(中断处理程序,等待队列函数中不能使用)
GFP_ATOMIC 在不允许睡眠的进程中使用,不会引起睡眠 */
vmalloc()和vfree()
vmalloc函数用来分配虚拟地址连续但是物理地址不连续的内存。vmalloc函数用来申请大量的内存。
void *vmalloc(unsigned long size);
void vfree(const void *addr);
后备高速缓存
在驱动程序中,会经常反复地分配很多同一大小的内存块,也会频繁的将这些内存块给释放掉。如果频繁的申请和释放内存,很容易产生内存碎片,使用内存池很好的解决了这个问题。在Linux中,为一些反复分配和释放的结构体预留了一些内存空间,使用内存池来管理,管理这种内存池的技术叫做slab分配器。这种内存叫做后备高速缓存。
创建slab缓存函数
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *))
分配slab缓存函数
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
销毁slab缓存函数
void kmem_cache_free(struct kmem_cache *c, void *b)
页面分配
Linux内核内存管理子系统提供了一系列函数用来进行内存分配和释放。为了方便管理,Linux中是以页为单位进行内存分配的。
在32位的机器上,一般一页大小为4KB。
在64位的机器上,一般一页大小为8KB。
当驱动程序的一个进程申请空间时,内存管理子系统会分配所请求的页数给驱动程序。如果驱动程序不需要内存时,也可以释放内存,将内存归还给内核为其他程序所用。
alloc_page()
alloc_pages()
__get_free_page()
__get_free_pages()
当不需要内存时,需要将内存还给内存管理系统,否则可能会造成资源泄露。
free_pages()
物理地址和虚拟地址之间的转换
将外部设备的IO端口物理地址映射到虚拟地址。
/* 物理地址映射到虚拟地址 */
void __iomem *ioremap(unsigned long paddr, unsigned long size)
/* 取消物理地址映射到虚拟地址 */
void iounmap (volatile void __iomem *addr);
对于嵌入式产品来说,一般外部设备处于内存空间中。在Linux中,为了方便编写驱动程序,对内存空间和IO空间的访问提供了一套统一的方法,这个方法是“申请资源->映射内存空间->访问内存->取消映射->释放资源”。