转载自:http://hi.baidu.com/liu_bin0101/blog/item/6feae7fa050c06819f5146dc.html
Linux 内核启动的时候,将system ram中的896M内存一一映射到3G~4G的空间去了,这也是为什么在内核中常出现物理地址到虚拟地址的转变只需加上一个常数0xC0000000的原 因。至于内核想访问其他的设备,比如说物理内存的高端地址抑或是外围设备的local ram或者是MMIO,都需要经过ioremap的函数,其实这个函数没有什么特别的地方,它只是将你指定的那段物理地址空间和3G~4G空间的专门用来 映射用的虚拟地址空间建立一个页表,到此为止,ioremap的所有工作算是完成了。接下来,如果某条指令要访问刚刚映射过的虚拟地址空间,那么它会经过 CPU的MMU运算,即该地址线离开CPU之后就是指向了刚刚ioremap的时候你传进去的物理地址空间了。至于这条地址线如何通过北桥的内存控制单元 到达你设备的MMIO,各家chip都有自己的实现方式。
另外:
1.像大家讨论的那样,物理内存被内核指令访问和被用户进程访问用的页表是各自独立的,这个比较重要。也即用户空间进程访问物理内存时,不会用到内核刚启动时候建立起来的一一映射的页表,而是自己建立了另外一个页表。 请注意一次映射所有物理内存到内核空间并不意味着这些物理内存被内核分配和占用了,只是在页表里有相应的记录而已。
系统映射896M内存是为了方便访问和管理physical memory,因为这样地址映射非常简单两者就差一个PAGE_OFFSET,而这种映射并不妨碍用户空间映射相同的地址。只要内核不会写已经被用户空间 映射的物理内存就好了。实际上真正每个进程的页表是拷贝kernel的页表3G-4G和自己的0-3G产生的。
2.之所以叫MMIO(memory map的io),意思是CPU将外围设备的寄存器看成跟内存一样的访问,因此对于CPU来说,基本分辨不出到底访问的是MMIO还是正常的物理内存,它所做的就是将拿到的指令的地址经过MMU运算到某个物理地址上去。
3.显卡之所以不占用3G~4G的vmalloc的虚拟地址空间,这跟X的实现有很大的关系,X本身就是一个用户进程,一个用户进程是不会在用户态用到内 核页表去访问相应的物理地址的,因此它要建立自己的页表来访问显卡的显存(即外围设备的local ram)。但是拿显卡的frame buffer driver来说,情况就不一样了,由于frame buffer driver是内核驱动,因此它最终还是需要调用ioremap来映射显卡的显存到3G~4G的虚拟地址空间来进行访问(可以参考nv的fb driver函数nvidiafb_probe或者intel的fb driver函数intelfb_pci_register)。
阅读(1410) | 评论(0) | 转发(1) |