精华内容
下载资源
问答
  • 页 页表 页表项
    千次阅读
    2020-11-03 10:17:08

    页 页表 页表项

    edgar_01112 2016-04-26 21:11:56 28031 收藏 35
    分类专栏: 计算机操作系统 文章标签: 操作系统

    //
    //操作系统和计算机组成原理里都讲到内存管理的页式管理,但是本人以及很多初次学习分页的时候,都会迷茫页表大小和页表项大小之间的关系,本人仔细分析了后写了这篇blog,仅当学习交流,个人理解之用,如果有错或者分析不够严谨,欢迎指正。
    //按字、图结合起来分析,相信还是比较容易看懂。

    //一、首先明确几个概念

    逻辑地址:是程序编译后,生成的目标模块进行编址时都是从0号单元开始编址,称之为目标模块的相对地址,即为逻辑地址。

    页:将进程划分的块,对应的大小就叫页面大小。

    页框:将内存划分的块。

    页和页框二者一一对应,一个页放入一个页框,(理论上)页的大小和页框的大小相等。

    页表:就是一个页和页框一一对应的关系表。【存放在内存中】 关系表只是起到一个索引的作用,说白了就是能根据关系表能查到某一个页面和哪一个页框所对应。

    //分页管理时,将若干字节视为一页,比如4K byte。此时,内存变成了连续的页,即内存为页数组,每一页物理内存叫页帧,以页为单位对内存进行编号,该编号可作为页数组的索引,又称为页帧号。。。。页帧号也叫页帧数

    //
    //二、用例子说话【例子出现在:《王道考研操作系统》的内存管理部分】

    已知条件:逻辑地址32位、页面大小4KB、页表项大小4B,按字节编址。

    分析:

     首先 32 位的虚拟地址可表示的进程大小应该是2^32B = 4GB(暂时别去想页号P占多少位,W占多少位)             
    

    2.(根据页的定义和页面大小的定义)将进程进行分页:

    3.我们已经知道了页面的数目为:2^20页。现在的迷茫点就在于页表项的问题上。
    上图在页表上已经给出了几个数据:20位,12位,32位,2^20项。一一解释如下【请结合上图一个一个数据分析】:

    2^20项:因为页表的作用是要将页面的页框一一对应起来,所以,每一个页面在页表中都应该有一个页表项:用来表示一个页号对应一页页框号(内存中的块号),故应     
    
                    该有2^20项。【不应该有问题吧,就好像一个班有50个同学,每个人都应该有一个地址一样】
    

    20位:已经很显然了,需要表示出2^20个页表项,就至少需要20位的地址。为什么只取20位而不是21位,22位呢,本人现在还没想这个问题,就暂时定为恰好取20位即可。

    32位:已知条件里告诉了页表项大小为4B,那么自然就应该是32位了。

    12位:32位-20位 = 12位。为什么页框号地址为12位,只能表示212个页框,要小于220个页面呢,因为并不是进程的每一个页面都要调入内存。其实32位、12位、20位这三个数据还是有一定依据的,在二级分页的时候就会发现“哦,原来刚刚好”。此处暂不讨论二级分页。

    4.通过上面的分析我们得出了哪些数据:

    逻辑地址32位,进程大小:4GB。

    页面:大小4KB,数量:2^20页。

    页表项:4B,数量:220项。所以页表就需要4B*220 = 4MB的空间存储(这就是书中说:页表项大小为4MB的由来)进一步,主存的页框大小和页面大小是相等的,也为4KB,所以将页表存在主存就需要占用4MB/4KB = 1024页(因为页表也是存在主存中的,而主存也是按页框划分的。这的确是一种资源浪费,所以就需要建立二级页面,将其大小控制在1页之内,将二级页面存入主存即可)

    页 页表 页表项
    edgar_01112 2016-04-26 21:11:56 28031 收藏 35
    分类专栏: 计算机操作系统 文章标签: 操作系统

    //
    //操作系统和计算机组成原理里都讲到内存管理的页式管理,但是本人以及很多初次学习分页的时候,都会迷茫页表大小和页表项大小之间的关系,本人仔细分析了后写了这篇blog,仅当学习交流,个人理解之用,如果有错或者分析不够严谨,欢迎指正。
    //按字、图结合起来分析,相信还是比较容易看懂。

    //一、首先明确几个概念

    逻辑地址:是程序编译后,生成的目标模块进行编址时都是从0号单元开始编址,称之为目标模块的相对地址,即为逻辑地址。

    页:将进程划分的块,对应的大小就叫页面大小。

    页框:将内存划分的块。

    页和页框二者一一对应,一个页放入一个页框,(理论上)页的大小和页框的大小相等。

    页表:就是一个页和页框一一对应的关系表。【存放在内存中】 关系表只是起到一个索引的作用,说白了就是能根据关系表能查到某一个页面和哪一个页框所对应。

    //

    //
    //二、用例子说话【例子出现在:《王道考研操作系统》的内存管理部分】

    已知条件:逻辑地址32位、页面大小4KB、页表项大小4B,按字节编址。

    分析:

     首先 32 位的虚拟地址可表示的进程大小应该是2^32B = 4GB(暂时别去想页号P占多少位,W占多少位)             
    

    2.(根据页的定义和页面大小的定义)将进程进行分页:

    3.我们已经知道了页面的数目为:2^20页。现在的迷茫点就在于页表项的问题上。
    上图在页表上已经给出了几个数据:20位,12位,32位,2^20项。一一解释如下【请结合上图一个一个数据分析】:

    2^20项:因为页表的作用是要将页面的页框一一对应起来,所以,每一个页面在页表中都应该有一个页表项:用来表示一个页号对应一页页框号(内存中的块号),故应     
    
                    该有2^20项。【不应该有问题吧,就好像一个班有50个同学,每个人都应该有一个地址一样】
    

    20位:已经很显然了,需要表示出2^20个页表项,就至少需要20位的地址。为什么只取20位而不是21位,22位呢,本人现在还没想这个问题,就暂时定为恰好取20位即可。

    32位:已知条件里告诉了页表项大小为4B,那么自然就应该是32位了。

    12位:32位-20位 = 12位。为什么页框号地址为12位,只能表示212个页框,要小于220个页面呢,因为并不是进程的每一个页面都要调入内存。其实32位、12位、20位这三个数据还是有一定依据的,在二级分页的时候就会发现“哦,原来刚刚好”。此处暂不讨论二级分页。

    4.通过上面的分析我们得出了哪些数据:

    逻辑地址32位,进程大小:4GB。

    页面:大小4KB,数量:2^20页。

    页表项:4B,数量:220项。所以页表就需要4B*220 = 4MB的空间存储(这就是书中说:页表项大小为4MB的由来)进一步,主存的页框大小和页面大小是相等的,也为4KB,所以将页表存在主存就需要占用4MB/4KB = 1024页(因为页表也是存在主存中的,而主存也是按页框划分的。这的确是一种资源浪费,所以就需要建立二级页面,将其大小控制在1页之内,将二级页面存入主存即可)

    页 页表 页表项
    edgar_01112 2016-04-26 21:11:56 28031 收藏 35
    分类专栏: 计算机操作系统 文章标签: 操作系统

    //
    //操作系统和计算机组成原理里都讲到内存管理的页式管理,但是本人以及很多初次学习分页的时候,都会迷茫页表大小和页表项大小之间的关系,本人仔细分析了后写了这篇blog,仅当学习交流,个人理解之用,如果有错或者分析不够严谨,欢迎指正。
    //按字、图结合起来分析,相信还是比较容易看懂。

    //一、首先明确几个概念

    逻辑地址:是程序编译后,生成的目标模块进行编址时都是从0号单元开始编址,称之为目标模块的相对地址,即为逻辑地址。

    页:将进程划分的块,对应的大小就叫页面大小。

    页框:将内存划分的块。

    页和页框二者一一对应,一个页放入一个页框,(理论上)页的大小和页框的大小相等。

    页表:就是一个页和页框一一对应的关系表。【存放在内存中】 关系表只是起到一个索引的作用,说白了就是能根据关系表能查到某一个页面和哪一个页框所对应。

    //

    //
    //二、用例子说话【例子出现在:《王道考研操作系统》的内存管理部分】

    已知条件:逻辑地址32位、页面大小4KB、页表项大小4B,按字节编址。

    分析:

     首先 32 位的虚拟地址可表示的进程大小应该是2^32B = 4GB(暂时别去想页号P占多少位,W占多少位)             
    

    2.(根据页的定义和页面大小的定义)将进程进行分页:

    3.我们已经知道了页面的数目为:2^20页。现在的迷茫点就在于页表项的问题上。
    上图在页表上已经给出了几个数据:20位,12位,32位,2^20项。一一解释如下【请结合上图一个一个数据分析】:

    2^20项:因为页表的作用是要将页面的页框一一对应起来,所以,每一个页面在页表中都应该有一个页表项:用来表示一个页号对应一页页框号(内存中的块号),故应     
    
                    该有2^20项。【不应该有问题吧,就好像一个班有50个同学,每个人都应该有一个地址一样】
    

    20位:已经很显然了,需要表示出2^20个页表项,就至少需要20位的地址。为什么只取20位而不是21位,22位呢,本人现在还没想这个问题,就暂时定为恰好取20位即可。

    32位:已知条件里告诉了页表项大小为4B,那么自然就应该是32位了。

    12位:32位-20位 = 12位。为什么页框号地址为12位,只能表示212个页框,要小于220个页面呢,因为并不是进程的每一个页面都要调入内存。其实32位、12位、20位这三个数据还是有一定依据的,在二级分页的时候就会发现“哦,原来刚刚好”。此处暂不讨论二级分页。

    4.通过上面的分析我们得出了哪些数据:

    逻辑地址32位,进程大小:4GB。

    页面:大小4KB,数量:2^20页。

    页表项:4B,数量:220项。所以页表就需要4B*220 = 4MB的空间存储(这就是书中说:页表项大小为4MB的由来)进一步,主存的页框大小和页面大小是相等的,也为4KB,所以将页表存在主存就需要占用4MB/4KB = 1024页(因为页表也是存在主存中的,而主存也是按页框划分的。这的确是一种资源浪费,所以就需要建立二级页面,将其大小控制在1页之内,将二级页面存入主存即可)

    更多相关内容
  • 1.页框(物理块):将内存空间分成一个个大小相等的分区(页框号或物理块号从0开始)。 2.页(页面):将用户进程的地址空间分为与页框大小...页面长度:指这个页总共有几个页面或页表项(下面有解释)。 页面大小...

    1.页框(物理块):将内存空间分成一个个大小相等的分区(页框号或物理块号从0开始)。watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiK5a2m6Lev5LiKLQ==,size_11,color_FFFFFF,t_70,g_se,x_16

     2.页(页面):将用户进程的地址空间分为与页框大小相等的一个个区域(页号一般也从0开始)。watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiK5a2m6Lev5LiKLQ==,size_8,color_FFFFFF,t_70,g_se,x_16

     因为要将进程中的页分别装入多个可以不相邻接的页框(物理块)中,且由于进程中的最后一页经常装不满一块,所以会产生内部碎片。(注:内部碎片是指分配给某进程的内存区域,有些部分没用上。如:分配给进程A4M,而该进程只占用了3M,剩余1M没使用,为内部碎片。)watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiK5a2m6Lev5LiKLQ==,size_10,color_FFFFFF,t_70,g_se,x_16

     页面长度:指这个页总共有几个页面或页表项(下面有解释)。

    页面大小:指一个页面占多大的存储空间。(一般为2的12次方,也就是4KB,详细内容可以去了解分页地址中的地址结构)。

    3.页表:系统为每个进程建立的页面映像表。在地址空间内的所有页(0~n),依次在页表中有一页表项,记录了相应页在内存块中对应的物理块号。(下图中间部分)watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiK5a2m6Lev5LiKLQ==,size_20,color_FFFFFF,t_70,g_se,x_16

    页表项:(下图中的橙色框部分)watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiK5a2m6Lev5LiKLQ==,size_20,color_FFFFFF,t_70,g_se,x_16

     页表项长度:指每个页表项占多大的内存空间。(每个页表项的长度是相同的)

    补充:

    页表在内存中占用的大小=页表长度×页表项长度;

    内存大小=页面长度×页面大小(物理块大小)

    举例:

    现在假设有2GB内存,页面大小为4KB,页表项大小为4B。那么它一共有2GB/4KB=512K个内存块(or页,内存块大小=页面大小),也就是说页表项有512K项(一个页表项对应一个块号),而每个页表项的大小4B,那么页表在内存中占用的大小是:512K*4B=2MB,意味着,只要2MB就可以表示512K个页(每个页是4KB,总内存大小是2G),它页表本身占用了2MB/4KB=512个页。

     

     

     

    展开全文
  • 页表项内容

    2021-08-11 15:17:29
  • 我们以ARM64四级页表为例,谈谈页表项里藏得是什么。 1 ~ 3 级表项 从__create_pgd_mapping函数开始看: static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, unsigned long virt, phys_...

    目录

    L0 L1 L2 表项

    L3 表项

    总结

    pgd_t

    不只是物理地址

    谈谈对映射的理解

    思考


    当你不去细细读代码的话,这个问题可能会困扰着你。我们以ARM64四级页表为例,谈谈页表项里藏得是什么。本文讨论的是内核线性映射过程时建立的临时页表,涉及到早期内核页表的建立不做分析,后面有机会分析吧。

    L0 L1 L2 表项

    从__create_pgd_mapping函数开始看:

    static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
    				 unsigned long virt, phys_addr_t size,
    				 pgprot_t prot,
    				 phys_addr_t (*pgtable_alloc)(void),
    				 int flags)
    {
    	unsigned long addr, length, end, next;
    //获取以virt在pgdir中的表项。
    	pgd_t *pgdp = pgd_offset_raw(pgdir, virt);
    
    	phys &= PAGE_MASK;
    	addr = virt & PAGE_MASK;
    	length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));
    
    	end = addr + length;
    	do {
    		next = pgd_addr_end(addr, end);
    //这一步会设计获取表项里的内容
    		alloc_init_pud(pgdp, addr, next, phys, prot, pgtable_alloc,
    			       flags);
    		phys += next - addr;
    	} while (pgdp++, addr = next, addr != end);
    }
    
    

    之前杂谈过页表项的坑比问题,明确了页表可以当成一个数组去看。

    pgd_t *pgdp = pgd_offset_raw(pgdir, virt) 可以看成 pgdir[index(virt)],那么 pgdp = &pgdir[index(virt)]。

    下面看 alloc_init_pud ,先看上半部分内容。

    static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
    			   phys_addr_t phys, pgprot_t prot,
    			   phys_addr_t (*pgtable_alloc)(void),
    			   int flags)
    {
    	unsigned long next;
    	pud_t *pudp;
    //获取表项里的内容
    	pgd_t pgd = READ_ONCE(*pgdp);
    //表项为空,填充内容
    	if (pgd_none(pgd)) {
    		phys_addr_t pud_phys;
    		BUG_ON(!pgtable_alloc);
    		pud_phys = pgtable_alloc();
    		__pgd_populate(pgdp, pud_phys, PUD_TYPE_TABLE);
    		pgd = READ_ONCE(*pgdp);
    	}
    
    }
    

    接着之前的传递参数,pgd_t pgd = READ_ONCE(*pgdp) 可以看成 pgd = pgdir[index(virt)],如果pgd为0,会从memblock中获取一个page大小的物理内存,然后把这个物理内存的起始物理地址与bm_pte关联。pgtable_alloc()为函数指针,实际调用early_pgtable_alloc。获取物理内存后,使用__pgd_populate,将这个物理内存的起始物理地址填到页表项中,即 pgdir[index(virt)] = pud_phys。实际上会把这个物理地址转换成pdt_t 类型,但不影响理解。

    所以页目录表的表项里存放的是物理地址,注意这个物理地址和映射的物理地址不是一个概念,是下级页表的物理地址。

    讲到这其实 pgdir[index(virt)] = pud_phys 这个说法是不严谨的,也是因为背后的真面目导致我们看不到物理地址。看如下函数

    static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pudp, pgdval_t prot)
    {
    	set_pgd(pgdp, __pgd(__phys_to_pgd_val(pudp) | prot));
    }
    
    #define __phys_to_pgd_val(phys)	__phys_to_pte_val(phys)
    #define __phys_to_pte_val(phys)	(phys)

    参数pudp定义成物理地址,里面又对其做了转化 __phys_to_pgd_val(pudp) ,在没有CONFIG_ARM64_PA_BITS_52,也就是定义的物理地址不是52位的情况下__phys_to_pgd_val(pudp) == pudp,依旧是物理地址。但是学问在  __pgd(__phys_to_pgd_val(pudp) | prot) 操作,将物理地址和属性结合在一块,重新定义成 pgd_t 类型,实现 phys_addr_t 到 pgd_t 转换,所以物理地址被盖上了一层纱,但要认清他还是物理地址,使用的时候需要揭开这个纱。

    typedef u64 pgdval_t;
    typedef struct { pgdval_t pgd; } pgd_t;
    #define pgd_val(x)	((x).pgd)
    #define __pgd(x)	((pgd_t) { (x) } )

    这个定义很神奇,文末做了一个简单分析。把一个数值强转成pgd_t类型,然后取里面的pgd成员。强转在内核中很常用,比如在ARM64开启vmemmap定义后,存放page的全局数组是由vmemmap这个虚拟地址强转成struct page来使用的

    继续往下

    static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
    			   phys_addr_t phys, pgprot_t prot,
    			   phys_addr_t (*pgtable_alloc)(void),
    			   int flags)
    {
        ...
            pudp = pud_set_fixmap_offset(pgdp, addr);
    	do {
    		next = pud_addr_end(addr, end);
    
     		if (use_1G_block(addr, next, phys) &&
    		    (flags & NO_BLOCK_MAPPINGS) == 0) {
    			pud_set_huge(pudp, phys, prot);
    		} else {
    			alloc_init_cont_pmd(pudp, addr, next, phys, prot,
    					    pgtable_alloc, flags);
    		}
    		 phys += next - addr;
    	} while (pudp++, addr = next, addr != end);
        ...
    }

    看 pudp = pud_set_fixmap_offset(pgdp, addr) ,主要搞清楚 如何 使用 pgdp 来获取pudp。pud_set_fixmap_offset 由两部分组成

    #define pud_set_fixmap_offset(pgd, addr)	pud_set_fixmap(pud_offset_phys(pgd, addr))
    
    第一部分 fixmap
    #define pud_set_fixmap(addr)		((pud_t *)set_fixmap_offset(FIX_PUD, addr))
    第二部分 获取pgd的内容,也就是pud的物理地址
    pud_offset_phys(pgd, addr)

    第二部分有很多路需要绕,一步步展开后

    #define pud_offset_phys(pgd, addr)
    (__pte_to_phys(__pte(pgd_val(*(pgd)))) + pud_index(addr) * sizeof(pud_t))
    
    #define __pte_to_phys(pte)	(pte_val(pte) & PTE_ADDR_MASK)
    #define PTE_ADDR_MASK		PTE_ADDR_LOW
    #define PTE_ADDR_LOW		(((_AT(pteval_t, 1) << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT)    //mask低12位为0

    首先获取pgd里面的内容,然后转成pte_t类型,再通过__pte_to_phys操作获取物理地址。为什么这么做,前面说过了,物理地址被盖上了一层纱,需要揭开面纱才能见到真正的物理地址。根据页表转化流程低12位是和物理地址没关系的,来自虚拟地址的offset,或者某些flag。

    后面的alloc_init_cont_pmd 操作就和pgd的操作一样了,先判断是不是空,如果为空就填充,然后映射下一级。

    L3 表项

    static void init_pte(pmd_t *pmdp, unsigned long addr, unsigned long end,
    		     phys_addr_t phys, pgprot_t prot)
    {
    	pte_t *ptep;
    
    	ptep = pte_set_fixmap_offset(pmdp, addr);
    	do {
    		set_pte(ptep, pfn_pte(__phys_to_pfn(phys), prot));
    
    		phys += PAGE_SIZE;
    	} while (ptep++, addr += PAGE_SIZE, addr != end);
    }
    

    四级表项区别于前三级表项的地方在set_pte函数的第二个参数,直接使用将要映射的物理地址。可以看到,pte里存放的只是物理页号+属性。所以默认一个pte囊括4KB的范围。至于具体的物理地址,在做地址翻译的时候,将虚拟地址的后12位作为目标物理页号开始的偏移,从而取得具体的物理地址。

    网上的地址转化示意图只是作为地址翻译去理解,如果作为地址建立过程去理解就翻车了。

    总结

    pgd表项存放的是下级页表pud的物理地址(memblock获取)和属性,pgd表项的地址是要建立映射的虚拟地址在pgdir中的偏移。

    pud表项存放的是下级页表pmd的物理地址(memblock获取)和属性,pud表项的地址是pud的物理地址(pgd表项里存放的)映射到bm_pud的虚拟地址。

    pmd表项存放的是下级页表pte的物理地址(memblock获取)和属性,pmd表项的地址是pmd的物理地址(pud表项里存放的)映射到bm_pmd的虚拟地址。

    pte表项存放的是要映射的物理地址(ddr地址)和属性,ptd表项的地址是ptd的物理地址(pmd表项里存放的)映射到bm_pte的虚拟地址。

    各个表项是虚拟地址,利用fixmap暂时性使用的(p*d_set_fixmap)。fixmap会将FIX_P*D地址放在bm_p*d数组中,具体参考early_fixmap_init和p*d_set_fixmap,这里不细说。

    其实可以发现,物理地址都是隐藏在参数中,直观给我们的都是虚拟地址,所以我们要抛弃物理地址的思维看os,从单片机的思维中走出来。

    pgd_t

    直接拷贝内核代码,编写一个程序来理解。体会一下把一个数值强转成pgd_t类型,然后抽离出成员pgd。

    #include <stdio.h>
    
    typedef unsigned long pteval_t;
    typedef struct { pteval_t pte; } pte_t;
    #define pte_val(x)	((x).pte)
    #define __pte(x)	((pte_t) { (x) } )
    
    typedef unsigned long pgdval_t;
    typedef struct { pgdval_t pgd; } pgd_t;
    #define pgd_val(x)	((x).pgd)
    #define __pgd(x)	((pgd_t) { (x) } )
    
    #define PA 			0x13ffff000
    #define PROT		3
    #define PTE_ADDR_MASK		(((1 << 36) - 1) << 12)
    
    int main()
    {
        pgd_t *pgdp;
        pte_t pte;
        pgd_t pgd = __pgd(PA|PROT);    
    
        pte = __pte(pgd_val(pgd));    //模拟set_pte
    
        int pa = (pte_val(pte) & PTE_ADDR_MASK);    //抽离出PA
    	
        printf("pa %x\n", pa);
    
        return 0;
    }

    ARM手册页表表述

    ARMv8架构支持的最大物理地址宽度为48位,页表本身是unsigned long类型占64位。由于物理地址按页管理,所以页表项里的物理地址是一个个页号。

    由此可以得出,如果按4K为单位,那么页表项中bit[47:12]存放的是物理页号,也就是物理地址,解析物理地址的时候就是解析bit[47:12],bit[11:0]沿用虚拟地址,拼凑出某个物理地址。

    那页表项中其余bit[63:48]和bit[11:0]和物理地址无关,但也不能浪费,用作属性和标志位管理。具体可见arch/arm64/include/asm/pgtable-hwdef.h中定义了一些页表项的描述符,arch/arm64/include/asm/pgtable-prot.h中定义了一些软件标志位属性,具体存放在哪个bit上这里不做阐述。

    附:参考ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile

    L0 ~ 3 表项 页表对应Table这行

    L3 表项 不同大小page,内容不同

    详细描述可以去阅读手册。

    谈谈对映射的理解

    玩过单片机的同学都知道,访问某个外设就直接给出外设地址然后像指针一样去操作,点灯就完成了。这里操作的是物理地址。

    在linux内核就不一样了,加了MMU,cpu看不到物理地址了,只能看到虚拟地址同时只能操作虚拟地址。好处就是让cpu感觉自己的空间很大很大,直接脱离了物理内存的视野。但是虚拟地址终归是虚的,操作这个地址是没有用的,有用的是物理地址,所以要把这些虚拟地址和物理地址建立关系,这样cpu操作虚拟地址就像在操作物理地址一样。内核中把映射好的地址以page为单位进行管理。程序是泡在内存中的,映射了内存就可以像点灯一样去操作内存了。

    当然对于其他外设模块(非ddr),可以直接使用ioremap映射到内核空间。

    用户空间运行程序也是要物理地址,如果泡在未映射物理地址的虚拟空间里,这时候是以缺页方式去获取一段物理空间。默认用户空间程序是以缺页方式建立。

    当然内核实现remap_pfn_range,这类通常是mmap,用户空间可以直接操作物理地址。

    当我们在写代码的时候malloc了一个空间,然后操作这个空间的时候说不定背后就跑了缺页异常代码去获取page了呢。

    思考

    1 页表项里面存放的是物理地址,那页表项本身存放的是什么?

    2 用户空间的页表项里存放的是什么?

    展开全文
  • 【操作系统/计组】页面大小、页表项、一级页表、多级页表的关系与计算
  • 页表由多个页表项组成,即页表中每一行的就是一个页表项页表项中记录的信息: 页框号:记录虚页面对应的具体哪个物理页面 有效位:标识该页表项对应的虚页面有没有读进内存,否则在磁盘 访问位:引用位,标识该...
  • 页、页表、页表项

    千次阅读 2019-10-17 17:39:05
    页表项的数目就等于页(面)数目即为2^20个,全部页表项(页表中从上往下数)所需的地址也就是20位。 红框即为一个页表项,以此类推。 4.物理块号的地址=逻辑地址-页号地址=32-20=12位,因为并不是进程的...
  • 展开全部一、理解这样一个概念,操作系统为了方便管理内存e69da5e887aa3231313335323631343130323136353331333431353936,将内存划分成很若干个页,每个页表项就代表一个页的地址(页的地址,不是内存地址)。...
  • 页目录项和页表项

    千次阅读 2020-09-01 01:07:40
    页目录项和页表项 上图就是页目录项和页表项的格式。可以看出,由于页表或者页的物理地址都是4KB对齐的(低12位全是零),所以上图中只保留了物理基地址的高20位(bit[31:12])。低12位可以安排其他用途。 【P】:...
  • 目录项和页表项

    千次阅读 2020-06-19 10:55:16
    每个目录项和页表项都是以4字节(32位机器)的长度存储的数据, 由于页面表和页面的起始地址都总是在4K字节的边界上, 这些指针的低12位都永远是0. 这样, 在目录项和页面表中都只要有20位的指针就够了, 余下的12位则可以...
  • 页表项多大? 首先需要抛开一级二级x级页表的概念。对于32位的地址空间,规定按4K一页来管理,可以分成2^32B / 4K = 2^20 个页。 所以32位机器,页号范围是 0 ~ 2^20-1,这点毋庸置疑。 现在要建造一样东西来...
  • 页面大小和页表项

    千次阅读 2020-08-14 10:47:44
    单级页表 假设某个系统物理内存大小为4GB,页面大小为4KB...若取3字节存储页表项,则一个页4096/3=1365个页表项4096%3=1产生1B的内部碎片,若取4字节存储页表项(至少3字节,所以可以取4),则一个页框刚好可以存储409
  • OS——关于页面大小与页表项的问题

    千次阅读 2021-02-05 23:50:08
    一、采用分页管理方式时,操作系统将进程划分成若干个页面,将内存划分为若干个内存块(or页),页面和内存块大小...页表是一种数据结构,其中每一项成为页表项,存放内存块号(每个页表项对应一个内存块),并且将页表...
  • 我在学习操作系统的时候在遇到页表项大小,页表项,页面大小的的误区,百度了好久也是很迷糊,现如今恍然大悟,今天给大家分享一下,希望大家不用迷路。 之前百度到了一个这样的问题,我曾经也有过这样的问题,如图...
  • 将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置。 于是可从中得到该页的物理块号,将之装入物理地址寄存器中。 列出式子出来:页表始址+页号x页表项长度 1)页表项长度是页面长度是吗? ...
  • 段、页、页框、页表、页表项

    万次阅读 多人点赞 2020-05-05 15:01:14
    段、页、页框、页表、页表项分页式虚拟内存:页、页框、页表、页表项段页式虚拟内存(分段+分页):段、段表、段表项、页、页框、页表、页表项 分页式虚拟内存: 页、页框、页表、页表项 页:进程中的块(进程被...
  • 页面大小和页表项的联系

    千次阅读 2020-05-13 13:51:44
    页表项用来将逻辑地址转化为物理地址,具体实现步骤为: 用逻辑地址高位的页号去页表项内索引,得到对应的物理帧(跟页一个概念)号 将物理帧号与逻辑地址地位的偏移量相加得到实际的物理地址 那页表项存在哪里呢? ...
  • 操作系统页表项长度问题的记录

    千次阅读 2020-06-24 22:01:29
    学习分页存储管理的过程中,对于每个页表项大小的下限如何确定这个问题不是很理解,经过一番周折终于弄懂,特此记录。 问题描述 以32位逻辑地址空间、字节编址单位、一页4KB为例,地址空间有232B / 4 KB = 1M页,...
  • MMU的页表查询过程介绍,涉及到页表项、页表、页面、VPN、PFN等等关系的理解,为Linux内核管理奠定基础
  • 【转;补充】分页存储管理中的页表项长度是什么?

    千次阅读 多人点赞 2018-12-02 21:06:13
    将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置。 于是可从中得到该页的物理块号,将之装入物理地址寄存器中。 列出式子出来: 页表始址+页号x页表项长度 看到这里其实大多数同学是完全不...
  • 逻辑地址空间、页表与如何确定页表项大小

    万次阅读 多人点赞 2018-10-17 23:38:14
    32位逻辑地址空间,一页4KB,按字节编制,页式内存管理中如何确定页表项大小 因为是32位逻辑地址,故寻址空间为2^32B,而一页大小为4KB,故需要2^32/4B=2^20页=1M页。假设在内存中地址: 而页表则是对这些页表的...
  • 页表项长度的计算方法

    千次阅读 2019-12-09 15:26:14
    Frame Number –  It gives the frame number in which the current page you are looking for is present. The number of bits required depends on ...用逻辑地址长度求页表项长度的,有一个算一个都是错的  
  • 页目录项和页表项低12位意义

    千次阅读 2019-07-21 22:33:19
    页目录项和页表项 上图就是页目录项和页表项的格式。可以看出,由于页表或者页的物理地址都是4KB对齐的(低12位全是零),所以上图中只保留了物理基地址的高20位(bit[31:12])。低12位可以安排其他用途。 ...
  • 首先要了解页表项是由【页号】【页框号】组成,因为是分页系统每一个页面大小都是一样的所以可以根据逻辑地址的大小推算出【页号】,也就是说页表项中的【页号】可以省略。 下边给出一个例子: 一个32位系统分页系统...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,638
精华内容 11,455
关键字:

页表项

友情链接: Functions.rar