本篇文章给大家谈谈linux页帧号怎么理解,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、请问什么是页帧
- 2、如何将虚拟地址转化成pfn,即页帧号麻烦告诉我
- 3、linux驱动是用静态映射还是动态映射好
- 4、linux kernel 内存管理-页表、TLB
- 5、linux采用什么方法实现内存的分配和释放
1、请问什么是页帧
就是块或称物理块、页框等,是分页存储管理方式中的一个概念,是物理内存对应虚拟内存页面大小相等的一个区域
2、如何将虚拟地址转化成pfn,即页帧号麻烦告诉我
用户程序中的虚拟地址,静态的是编译时就定好的,动态的(如malloc),是通过内核的页式内存管理在vma中定的,需要找到进程的task_struct中的页表然后一级级的翻译得到物理地址。
实际编译时定的地址叫做逻辑地址,这个逻辑地址是需要段式管理来翻译的,即段基址加段内偏移,由于linux中的这个段基址就是0,所以逻辑地址就直接对应了虚拟地址了。
这样得到物理地址以后,首先将十六进制的低三位与成0,这样做是得到页的物理地址,这里指4K页的情况,然后通过页的物理地址减去mem_map的第一个元素的地址就得到了此页在mem_map数组中的下标(此处注意指针相减不是指针表示的地址相减,而是两者之间指针所表示元素类型的个数),此下标即为pfn,知道了在数组中的下标就可以得到struct page结构体了,就可以知道page的所有情况了。
3、linux驱动是用静态映射还是动态映射好
样。
注:以下代码在内核目录linux-2.6.29/arch/arm/mach-s3c2440/mach-mini2440.c。
静态映射的建立方法,是在内核启动的时候,读取struct
map_desc结构体里面的成员:
/*arch/arm/include/asm/mach/map.h*/
14
struct
map_desc
{
15
unsigned
long
virtual;
//存放以后需要操作的虚拟地址,由自己定义
16
unsigned
long
pfn;
//需要操作的硬件的物理地址对应的页帧号,即物理地址右移12
17
unsigned
long
length;
//需要映射的大小
18
unsigned
int
type;
//类型
19
};
这里要说明两个成员:
1)物理地址的页帧号pfn:如果你了解linux的页式管理,那你应该知道,一个页的大小是4096B(2
12),所以一个地址的31-12位是用来表示一个地址对
4、linux kernel 内存管理-页表、TLB
页表用来把虚拟页映射到物理页,并且存放页的保护位(即访问权限)。
在Linux4.11版本以前,Linux内核把页表分为4级:
页全局目录表(PGD)、页上层目录(PUD)、页中间目录(PMD)、直接页表(PT) 。
4.11版本把页表扩展到5级,在页全局目录和页上层目录之间增加了 页四级目录(P4D) 。
各处处理器架构可以选择使用5级,4级,3级或者2级页表,同一种处理器在页长度不同的情况可能选择不同的页表级数。可以使用配置宏CONFIG_PGTABLE_LEVELS配置页表的级数,一般使用默认值。
如果选择4级页表,那么使用PGD,PUD,PMD,PT;如果使用3级页表,那么使用PGD,PMD,PT;如果选择2级页表,那么使用PGD和PT。 如果不使用页中间目录 ,那么内核模拟页中间目录,调用函数pmd_offset 根据页上层目录表项和虚拟地址获取页中间目录表项时 , 直接把页上层目录表项指针强制转换成页中间目录表项 。
每个进程有独立的页表,进程的mm_struct实例的成员pgd指向页全局目录,前面四级页表的表项存放下一级页表的起始地址,直接页表的页表项存放页帧号(PFN) 。
内核也有一个页表, 0号内核线程的进程描述符init_task的成员active_mm指向内存描述符init_mm,内存描述符init_mm的成员pgd指向内核的页全局目录swapper_pg_dir 。
ARM64处理器把页表称为转换表,最多4级。ARM64处理器支持三种页长度:4KB,16KB,64KB。页长度和虚拟地址的宽度决定了转换表的级数,在虚拟地址的宽度为48位的条件下,页长度和转换表级数的关系如下所示:
ARM64处理器把表项称为描述符,使用64位的长描述符格式。描述符的0bit指示描述符是不是有效的:0表示无效,1表示有效。第1位指定描述符类型。
在块描述符和页描述符中,内存属性被拆分为一个高属性和一个低属性块。
处理器的MMU负责把虚拟地址转换成物理地址,为了改进虚拟地址到物理地址的转换速度,避免每次转换都需要查询内存中的页表,处理器厂商在管理单元里加了称为TLB的高速缓存,TLB直译为转换后备缓冲区,意译为页表缓存。
页表缓存用来缓存最近使用过的页表项, 有些处理器使用两级页表缓存 : 第一级TLB分为指令TLB和数据TLB,好处是取指令和取数据可以并行;第二级TLB是统一TLB,即指令和数据共用的TLB 。
不同处理器架构的TLB表项的格式不同。ARM64处理器的每条TLB表项不仅包含虚拟地址和物理地址,也包含属性:内存类型、缓存策略、访问权限、地址空间标识符(ASID)和虚拟机标识符(VMID)。 地址空间标识符区分不同进程的页表项 , 虚拟机标识符区分不同虚拟机的页表项 。
如果内核修改了可能缓存在TLB里面的页表项,那么内核必须负责使旧的TLB表项失效,内核定义了每种处理器架构必须实现的函数。
当TLB没有命中的时候,ARM64处理器的MMU自动遍历内存中的页表,把页表项复制到TLB,不需要软件把页表项写到TLB,所以ARM64架构没有提供写TLB的指令。
为了减少在进程切换时清空页表缓存的需要,ARM64处理器的页表缓存使用非全局位区分内核和进程的页表项(nG位为0表示内核的页表项), 使用地址空间标识符(ASID)区分不同进程的页表项 。
ARM64处理器的ASID长度是由具体实现定义的,可以选择8位或者16位。寄存器TTBR0_EL1或者TTBR1_EL1都可以用来存放当前进程的ASID,通常使用寄存器TCR_EL1的A1位决定使用哪个寄存器存放当前进程的ASID,通常使用寄存器 TTBR0_EL1 。寄存器TTBR0_EL1的位[63:48]或者[63:56]存放当前进程的ASID,位[47:1]存放当前进程的页全局目录的物理地址。
在SMP系统中,ARM64架构要求ASID在处理器的所有核是唯一的。假设ASID为8位,ASID只有256个值,其中0是保留值,可分配的ASID范围1~255,进程的数量可能超过255,两个进程的ASID可能相同,内核引入ASID版本号解决这个问题。
(1)每个进程有一个64位的软件ASID, 低8位存放硬件ASID,高56位存放ASID版本号 。
(2) 64位全局变量asid_generation的高56位保存全局ASID版本号 。
(3) 当进程被调度时,比较进程的ASID版本号和全局版本号 。如果版本号相同,那么直接使用上次分配的ASID,否则需要给进程重新分配硬件ASID。
存在空闲ASID,那么选择一个分配给进程。不存在空闲ASID时,把全局ASID版本号加1,重新从1开始分配硬件ASID,即硬件ASID从255回绕到1。因为刚分配的硬件ASID可能和某个进程的ASID相同,只是ASID版本号不同,页表缓存可能包含了这个进程的页表项,所以必须把所有处理器的页表缓存清空。
引入ASID版本号的好处是:避免每次进程切换都需要清空页表缓存,只需要在硬件ASID回环时把处理器的页表缓存清空 。
虚拟机里面运行的客户操作系统的虚拟地址转物理地址分两个阶段:
(1) 把虚拟地址转换成中间物理地址,由客户操作系统的内核控制 ,和非虚拟化的转换过程相同。
(2) 把中间物理地址转换成物理地址,由虚拟机监控器控制 ,虚拟机监控器为每个虚拟机维护一个转换表,分配一个虚拟机标识符,寄存器 VTTBR_EL2 存放当前虚拟机的阶段2转换表的物理地址。
每个虚拟机有独立的ASID空间 ,页表缓存使用 虚拟机标识符 区分不同虚拟机的转换表项,避免每次虚拟机切换都要清空页表缓存,在虚拟机标识符回绕时把处理器的页表缓存清空。
5、linux采用什么方法实现内存的分配和释放
Linux 采用 Buddy 算法有效分配和释放物理页块。
linux系统内存管理的特点linux的进程结束后,它占用的资源全部释放,但是内存仅仅是设置了标志,标志了这部分内存已经不再使用,可以被重新分配的。当进程需要内存时,linux系统首先从空闲内存中查找分配,空闲内存不足时就会使用不再使用的内存;另外,如果你的程序又一次运行,系统直接使用内存中
的数据,不再从文件系统读组,提高了效率。这样一来,linux的系统使用律会很高,服务器的在98%以上;这样做的目的是:linux认为内存是最宝贵
的资源,充分利用,不能让他空闲
linux页帧号怎么理解的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、linux页帧号怎么理解的信息别忘了在本站进行查找喔。