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_virt - IO空间访问函数
inb
outb
inw
outw
inl
outl
insb
outsb
insw
outsw
insl
outsl - IO内存空间访问函数
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_region - io内存
request_region
ioport_map
ioread8
iowrite8
….
ioport_unmap
release_region
request_mem_region
ioremap
ioread8
iowrite8
…
iounmap
release_mem_region
2内核空间映射
说明:
可以将内存中的保留页映射到用户空间,保留页是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;
}
- 实现fileoperations中mmap函数
实现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