gcc小常识之内功提升
GCC不仅仅是个本地编译器----它还能够跨平台编译程序,即为不同于GCC本身所运行的系统生成可执行文件。这就可以为不能运行编译器的嵌入式系统编译软件。
GCC不仅仅是个本地编译器----它还能够跨平台编译程序,即为不同于GCC本身所运行的系统生成可执行文件。这就可以为不能运行编译器的嵌入式系统编译软件。
在内核地址空间中为kmap和vmalloc各保留了一段地址空间。linux内核使用vm_struct结构体表示映射的地址空间,并且被组织在链表vmlist中,同时为了快速搜索VMA中一块连续的虚拟地址空间采用了红黑树进行管理,另外根据红黑树的层次结构将红黑树的各节点信息保存在vmap_area_list双向链表中。
在编写linux设备驱动程序时经常使用ioremap接口将外设的物理地址转换成虚拟地址,继而通过访问内存的方式来访问外设物理地址空间的内容。下来就详细看下ioremap的具体流程。在ARM上,ioremap相关的操作api如下
当CPU拿到虚拟地址去访问实际物理地址的数据时,需要从MMU的页表查询某个虚拟地址对应的实际物理地址,在某款平台中有双核A9和ARM11两种CPU。A9的MMU页表是由linux管理和创建的,ARM11运行的是rtthreaed,MMU页表是在系统启动前预先创建好的。ARM11属于ARMv6架构,其MMU需要两级页表来映射物理地址,第一级页表为段映射,一个页表条目表示1M空间;第二级页表为页映射,一个页表条目表示4K空间
MMU是通过页表来查询虚拟地址与物理地址的映射关系。有时候,应用层需要直接访问物理地址,这时应用层就需要调用应用层mmap接口继而调用驱动层的mmap接口将希望的物理地址映射成用户态能访问的虚拟地址。由于操作系统事先并没有创建这块物理地址与虚拟地址的映射关系,因此在驱动层的mmap接口中,需要在页表中建立这块物理地址与虚拟地址的映射关系。其中,内核会在进程的虚拟空间查找一块连续的虚拟地址并把虚拟地址的起始和结束地址填充到VMA的vm_start和vm_end字段中,然后调用remap_pfn_range()在页表中建立物理地址与虚拟地址的映射关系。