📄 -+
字号:
any problems,send mails to lysindybear@sina.com.cn
相关文件
/include/asm-i386/highmem.h
内存映射是一个比较头疼的问题。简要介绍
进程的内存
task struct
mm---------->mm_struct
mmap----------------->vm_struct
pgd vm_next---->vm_struct
| vm_op------>vm_operations_struct
| *open
|--->pgd--->pte *close
| *nopage
|->pte
|
|->pte---->page_frame(页框)
|……
当系统对一段vm内存区域进行映射的时候,就对pgd表进行操作,首先从vm的start地址找到相应的pgd表中所
对应的页表项,然后分配页表项,但并不分配页框???
**********************两种内存映射模式***************************************
第一种内存映射模式是内核态的内存分配和映射,使用vmalloc和vfree,他们的主要作用是在高端内存
例如3G+physical_mem+8M------4G-8M这一段虚拟内存地址内分配一段连续的虚拟内存,这也就是内核才能
使用的高于3G的地址。因为内核也有可能使用大段的地址。
第二种模式就是用户使用的模式,只能映射0--3G这一段的地址,这种功能的实现实在将可执行文件加载到
内存中的过程中进行的,在使用do_mmap的时候,就进行检测,如果内存大于3G就放弃,认为没有内存可用了。
而do_mmap是从一个可执行文件装载到内存中,然后映射到虚拟内存中的必经之路。所以在用户态的程序是
没有办法来突破3G的限制的
****************************************************************************
当前32位linux将内存分为0--3G的用户空间,3G--4G的内核空间,由于系统需要将所有的物理内存映射到
内核空间去,所以,内核虚空间根本不够用,另外由于需要进行虚存分配时候的内存隔离,以及顶端的约100多
兆的虚空间需要用作其他的用途,所以留给系统能够映射的内核虚地址只有约890M左右,当机器上的物理内存
超过这个限制以后,那些高于这个地址的内存就叫做high_memory。所有的这些物理内存页都有相应的页结构,
但是对于high_memory这条分界线以下的页结构中的virtual属性是有意义的,对应的就是这个内存页开始的物理
地址所对应的内核虚地址,但是分界线以上的内存页的结构中的virtual就是0,因为,很明显,没有内核虚地址
和他们象对应,但是操作系统都是使用虚地址进行访问的,我们怎么访问分界线以上的内存页呢???
如果我们要使用这些high_memory,就必须使用一定的技巧将那些没有内存页赋一个虚地址。
使用的方法就是在内核虚地址空间划出一小片区域,当我们要使用high_memory以上的内存时候,就从这一小片
保留的内核虚地址中选一个出来,赋给这个内存页,内核就可以访问了。
一般这个虚地址池大约2M
另外一种内存映射方法是使用ioremap,道理时一样的。但是和kmap有一点不同,kmap一次映射一个整页的地址,
但ioremap只映射你给定的一个32位地址,所以当内存大于4G的时候,ioremap就无能为力了。
无论是ioremap还是kmap,我们可以看出,虚地址池是有限的,所以使用完ioremap或着kmap以后,一定要调用
相应的iounmap和kunmap释放所占有的虚地址。否则,当虚地址池中的地址耗完以后,就无法kmap成功了。
特别强调一点:在中断中使用kmap的时候,要使用kmap_atomic,主要是避免休眠等待,这是中断不允许的。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -