Linux内存访问(Liunx驱动3)

来源:互联网 发布:it到dt是什么意思 编辑:程序博客网 时间:2024/06/10 14:30

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;
      }

实现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

0 0
原创粉丝点击