1 内存与IO访问 说明:
从操作系统角度内存可分为内存空间和IO空间,对于x86系统存在IO空间,但是对于arm系统只有内存空间. 内存空间,在linux系统中又分为用户内存和内核内存.用户内存在0~3G范围,内核内存在3G~4G范围.用户程序运行在用户内存中,各个用户具有自己的空间,互相不干扰.内核运行在内核内存中,具有固定分配. 内核内存从高向低分为几个部分:保留区,专用页面分配区,高端内存映射区,vmalloc分配区,物理内存映射区.vmalloc分配区与前后区之间有一定的间隔.物理映射区映射物理0~896M的内存,高于此地址的物理内存映射到高端内存映射区。 地址可分为物理地址,总线地址,虚拟地址. 高性能cpu一般具有mmu内存管理单元,其中包括tlb和ttw。tlb是转换旁路缓存,ttw是转换表漫游。当处理器给出地址后,具有mmu的cpu首先会查找tlb,如果没有找到会在ttw中查找,查找到后将地址放入tlb中。
变量:
kmem_cache_t slab缓存结构,用于slab缓存. struct vma_area_struct vma结构,用于内存空间映射 成员:{ struct mm_struct *vm_mm; unsigned long vm_strat;//虚拟空间起始地址 unsigned long vm_end; pgprot_t vm_page_prot; unsigned long vm_flags; vm_operations_struct *vm_ops;//操作函数 … } struct map_spec 用于静态空间映射.
函数:
kmalloc (size_t size,int flags) flags一般有GFP_KERNEL,GFP_ATOMIC,GFP_DMA等.使用GFP_KERNEL标志会导致阻塞,而使用GFP_ATOMIC不会导致阻塞. kfree __get_free_pages(unsigned int flags,unsigned int order) vmalloc (unsigned long size) vfree
slab相关函数,slab是为了提高内存的使用效率,为频繁分配小内存使用而提出的解决方案.kmalloc就是用slab实现的.kmem_cache_create kmem_cache_alloc kmem_cache_free kmem_cache_destory
内存池相关函数 mem_pool_create mem_pool_alloc mem_pool_free mem_pool_destory低端内存的物理地址与虚拟地址的转换 virt_to_phys phys_to_virt virt_to_page virt_to_bus bus_to_virtIO空间访问函数 inb outb inw outw inl outl insb outsb insw outsw insl outslIO内存空间访问函数 ioremap(unsigned long offset,unsigned long size) 将物理地址映射到虚拟地址 iounremap ioport_map ioport_unmap ioread8 readb iowrite8 writeb ioread16 readw iowrite16 writew ioread32 readl iowrite32 writel request_region release_region request_mem_region release_mem_region用于内核空间到用户空间内存映射函数 remap_pfn_range(struct vma_area_struct *,unsigned long start,unsigned long pfn,unsigned long size,pgprot_t prot)//创建页表 remap_page_range(unsigned long start,unsigned long page,unsigned long pagesize,pgprot_t prot)// mem_map_reserve(unsigned long page) pgprot_nocached(pgprot_t prot)//将page设置为no cache,一般io空间都要设置为no cache用户侧: mmap(void* addr,size_t len,int prot,int flags,int fd,off_t offset)
prot:PROT_READ,PROT_WRITE,PROT_EXEC... flags:MAP_SHARE,MAP_PRIVATE,MAP_ANONYMOUS...munmap(void *addr,int len)
用法:
io空间 request_region inb outb … release_regionio内存 request_region ioport_map ioread8 iowrite8 …. ioport_unmap release_region request_mem_region ioremap ioread8 iowrite8 … iounmap release_mem_region2内核空间映射
说明:
可以将内存中的保留页映射到用户空间,保留页是IO空间,或者通过程序设置.
用法:
用户端: 调用mmap函数 mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); … munmap();
内核:
实现fileoperations中mmap函数 xx_mmap(struct file *file,struct vm_area_struct *vm) { remap_pfn_range(vm,vm->vm_start,vm->vm_pgoff,vm-vm_end-vm->vm_start,vm->vm_page_prot); vm->vm_ops=xx_vm_ops; } sturct vm_operations_struct xx_vm_ops={ .open=xx_open; .close=xx_close; }实现kmalloc分配内存的映射
xx_init{ share_mem=kmalloc(); for(page=virt_to_page(share_mem);page<virt_to_page(share_mem+BUFFER_SIZE);page++) mem_map_reserve(page);将mem设置为保留页 } xx_mmap(struct file*file,struct vm_area_struct *vm) { pos=(unsigned long)sheare_mem; start=vm->vm_start; while(size>0){ page=virt_to_phys(pos); remap_page_range(start,page,PAGE_SIZE,PAGE_SHARED); pos+=PAGE_SIZE; start+=PAGE_SIZE; size-=PAGE_SIZE; } } xx_exit() {kfree(); }3 DMA操作 说明:
dma操作,可能导致cache不一致的情况,所以应当使用dma_alloc_coherent方法申请dma内存.dma的使用类似于中断.
变量:
struct scatterlist
函数:
void *dma_alloc_coherent(struct device*dev,size_t size,dma_addr_t *handler,gfp_t gfp) dma_free_coherent(struct device*dev,size_t size,void *cpu_addr,gfp_t gfp) request_dma(unsigned int dmanr,const char*device_id); free_dma(unsigned int dmanr);
用法:
request_dma() dma_alloc_coherent read,write,ioctl dma_free_coherent free_dma