1.在linux系统中,进程的4GB内存空间一般分为用户空间(0~3)G和内核空间(3~4)G.
内核空间中,从低地址到高地址依次为:
物理内存映射区
隔离带
vmalloc虚拟内存分配器
隔离带
--------------------------------896M
高端内存映射区
专用页面映射区
保留区
2.内存存取
2.1 用户空间内存分配函数malloc函数通过brk()、mmap()两个系统调用来实现。
2.2 内核空间内存动态申请
kmalloc()、__get_free_pages()申请的内存位于物理内存映射区域。与物理地址存在简单换算关系。
2.2.1
kmalloc()函数的常用分配标志:
GFP_KERNEL暂时不能申请到内存时,进程会进入睡眠等待页, 不可用于中断上下文或者持有自旋锁的情况下。
GFP_ATOMIC 申请不到内存,直接返回 ,不等待。
kmalloc()<->kfree()
2.2.2
__get_free_pages(unsigned int flags,unsigned intorder)
分配多个页,并返回分配内存的首地址,分配的页数为2的order次幂。
__get_zeroed_page()
分配的页清零。
__get_free_page()
__get_free_pages(unsigned int flags,unsigned int order)中order为零
__get_free_pages()<->free_pages().
__get_free_page()<->free_page().
__get_free_pages,__get_free_page的实现中调用了alloc_pages()函数,alloc_pages()既可以在内核空间分配,也
可以在用户空间分配,返回值为分配的第一个页的描述符而非首地址。
2.2.3
vmalloc()申请的虚拟内存位于虚拟内存区域中。映射一块连续的内存,但是对应的物理内存并不一定连续。
vmalloc()不能用于原子上下文中,其内部实现使用了标志位GFP_KERNEL的kmalloc()
vmalloc()<->vfree()
2.2.4
slab算法,如果我们用合适的方法使得在对象前后两次被使用时分配在同一块内存或同一类内存空间且保留了基本的
数据结构,就可以大大提高效率,实际上kmalloc()即是使用了slab机制实现的。
内存池技术也是一种非常经典的用于分配大量小对象的后备缓存技术
2.3虚拟地址与物理地址关系
phys_to _virt #define __phys_to_virt(x) ((x)-PHYS_OFFSET+PAGE_OFFSET)
virt_to_phys #define __virt_to_phys(x) ((x)-PAGE_OFFSET+PHYS_OFFSET)
这两个函数仅适用于低端内存(896M以下)
3 设备i/o端口和i/o内存访问
i/o端口 request_region()->ioport_map()->ioread()/iowrite()->ioport_unmap()->release_region()
i/o内存 request_mem_region()->ioremap()->ioread()/iowrite()->ioumap()->release_mem_region()
1.申请资源 设备驱动加载或open函数中进行
2.映射到内核空间虚拟地址
3编程接口访问 设备驱动初始化、write、read、ioctl等函数中进行
4释放内存资源 模块卸载或release中进行