struct page&&pfn&&page frame

页(page):针对虚拟地址而言的一个概念,是线性地址被分为固定长度的单位组(典型大小为4k).页内部连续的线性地址被映射到连续的物理地址中.

页框(page frame):针对物理地址的一个概念。物理内存被分为固定的长度的存储区域,该区域页框也叫物理页。内核中使用struct page来描述一个物理页。

物理页框号(PFN):物理页区域中所有物理地址右移n位(n表示物理页大小转化为二进制的位数)如图1所示.

1.物理页框号

struct page

由上可知struct page用来关联描述物理页的.下面看看该结构体的内核源码实现:(下面是伪代码不是内核真正的实现)

//include/linux/mm_types.h
struct page {
    unsigned long flags;
    struct address_space *mapping;
    unsigned long index;   
    atomic_t _mapcount;
    atomic_t _refcount;
    struct list_head lru; 
    unsigned long private;     
    ...  
} 

由于每个物理页都要用一个一个struct page结构提来描述因此,为了节约内存struct page用了大量联合体,上面只是列举常用的一些常用的字段

(1)flag

该字段描述page的状态或者其他属性,参考下图:

2.page---flag数据描述

section:主要用于稀疏内存模型SPARSEMEM(设计到内存模型问题)

node:NUMA节点号,标识该page属于哪一个节点。
zone:内存域标志,标识该page属于哪一个zone。
flag:page的状态标识,常用的有:

//include/linux/page_flags.h
enum pageflags {
	PG_locked,		/* 表示页面已上锁,不要访问 */
	PG_error,     /* 表示页面发生IO错误 */
	PG_referenced, /* 用于RCU算法 */
	PG_uptodate,   /* 表示页面内容有效,当该页面上读操作完成后,设置该标志位 */
	PG_dirty,      /* 表示页面是脏页,内容被修改过 */
	PG_lru,        /* 表示该页面在lrc链表中 */
	PG_active,     /* 表示该页面在活跃lru链表中 */
	PG_slab,       /* 表示该页面是属于slab分配器创建的slab */
	PG_owner_priv_1,	/* 页面的所有者使用,如果是pagecache页面,文件系统可能使用*/
	PG_arch_1,       /* 与体系架构相关的页面状态位 */
	PG_reserved,     /* 表示该页面不可被换出,防止该page被交换到swap */
	PG_private,		/* 如果page中的private成员非空,则需要设置该标志,如果是pagecache, 包含fs-private data */
	PG_private_2,		/* 如果是pagecache, 包含fs aux data */
	PG_writeback,		/* 页面正在回写 */
	PG_head,		/* A head page */
	PG_swapcache,		/* 表示该page处于swap cache中 */
	PG_mappedtodisk,	/* 表示page中的数据在后备存储器中有对应 */
	PG_reclaim,		/* 表示该page要被回收,决定要回收某个page后,需要设置该标志 */
	PG_swapbacked,		/* 该page的后备存储器是swap/ram,一般匿名页才可以回写swap分区 */
	PG_unevictable,		/* 该page被锁住,不能回收,并会出现在LRU_UNEVICTABLE链表中,它包括的几种page:ramdisk或ramfs使用的页、shm_locked、mlock锁定的页 */
#ifdef CONFIG_MMU
	PG_mlocked,		/* 该page在vma中被锁定,一般是通过系统调用mlock()锁定了一段内存 */
#endif
#ifdef CONFIG_ARCH_USES_PG_UNCACHED
	PG_uncached,		/* 该page是uncache的 */
#endif
#ifdef CONFIG_MEMORY_FAILURE
	PG_hwpoison,		/* hardware poisoned page. Don't touch */
#endif
#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
	PG_young,
	PG_idle,
#endif
	__NR_PAGEFLAGS,

	/* Filesystems */
	PG_checked = PG_owner_priv_1,

	/* Two page bits are conscripted by FS-Cache to maintain local caching
	 * state.  These bits are set on pages belonging to the netfs's inodes
	 * when those inodes are being locally cached.
	 */
	PG_fscache = PG_private_2,	/* page backed by cache */

	/* XEN */
	/* Pinned in Xen as a read-only pagetable page. */
	PG_pinned = PG_owner_priv_1,
	/* Pinned as part of domain save (see xen_mm_pin_all()). */
	PG_savepinned = PG_dirty,
	/* Has a grant mapping of another (foreign) domain's page. */
	PG_foreign = PG_owner_priv_1,

	/* SLOB */
	PG_slob_free = PG_private,

	/* Compound pages. Stored in first tail page's flags */
	PG_double_map = PG_private_2,

	/* non-lru isolated movable page */
	PG_isolated = PG_reclaim,
};

内核中提供了一些标准宏,用来检查、操作某些特定的比特位,如:

PageXXX(page):检查page是否设置了PG_XXX位
SetPageXXX(page):设置page的PG_XXX位
ClearPageXXX(page):清除page的PG_XXX位
TestSetPageXXX(page):设置page的PG_XXX位,并返回原值
TestClearPageXXX(page):清除page的PG_XXX位,并返回原值

(2) mapping

mapping:有三种含义

  •       如果mapping = 0,说明该page属于交换缓存(swap cache)当需要使用地址空间时会指定交换分区的地址空间swapper_space
  •       如果mapping != 0,bit[0] = 0,说明该page属于页缓存或文件映射,mapping指向文件的地址空间address_space
  •       如果mapping != 0,bit[0] != 0,说明该page为匿名映射,mapping指向struct anon_vma对象,通过mapping恢复anon_vma的方法:anon_vma = (struct anon_vma *)(mapping - PAGE_MAPPING_ANON)

(3) index

表示该page在文件内的offset(以page size为单位)即是在映射的虚拟空间(vma_area)内的偏移;一个文件可能只映射一部分,假设映射了1M的空间,index指的是在1M空间内的偏移,而不是在整个文件内的偏移

(4)_mapcount

被页表映射的次数,也就是说该page同时被多少个进程共享。即是表示该page frame被映射的个数,也就是多少个page table entry中含有这个page frame的pfn.

 (5)  _refcount

表示引用计数。当count值为0时,该page frame可被free掉;如果不为0,说明该page正在被某个进程或者内核使用,调用page_count()可获得count值。

ps:注意区分_count和_mapcount,_mapcount表示的是映射次数,而_count表示的是使用次数;被映射了不一定在使用,但要使用必须先映射

(6) lru

是"least recently used"的缩写,根据page frame的活跃程度(使用频率),一个可回收的page frame要么挂在active_list双向链表上,要么挂在inactive_list双向链表上,以作为页面回收的选择依据,lru中包含的就是指向所在链表中前后节点的指针

(7) private

private:私有数据指针,由应用场景确定其具体的含义:

  •         a:如果设置了PG_private标志,表示buffer_heads;
  •         b:如果设置了PG_swapcache标志,private存储了该page在交换分区中对应的位置信息swp_entry_t。
  •         c:如果_mapcount = PAGE_BUDDY_MAPCOUNT_VALUE,说明该page位于伙伴系统,private存储该伙伴的阶。

参考:(1)https://blog.csdn.net/farmwang/article/details/66975345

             (2)https://zhuanlan.zhihu.com/p/68465952

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值