1、复合页的定义:

  复合页(Compound Page)就是将物理上连续的两个或多个页看成一个独立的大页,它可以用来创建hugetlbfs中使用的大页(hugepage),  也可以用来创建透明大页(transparent huge page)子系统。但是它不能用在页缓存(page cache)中,这是因为页缓存中管理的都是单个页。

2、复合页的分配及标记:

  当__alloc_pages分配标志gfp_flags指定了__GFP_COMP,那么内核必须将这些页组合成复合页compound page。复合页的尺寸要远大于当前分页系统支持的页面大小。并且一定是2^order * PAGE_SIZE大小。复合页主要用在HugeTLB相关的代码。复合页的引入是因为随着计算机物理内存容量不断增大,4G以上几乎成了标配,几十G的内存也很常见,而操作系统仍然使用4KB大小页面的基本单位,显得有些滞后。当采用4KB大小的页面时,想像一下当应用程序分配2MB内存,并进行访问时,共有512个页面,操作系统会经历512次TLB miss和512次缺页中断后,才可以把这2M地址空间全部映射到物理内存上;然而如果使用2MB大小的compand页,那么只需要一次TLB miss和一次缺页中断。当页面分配函数使用GFP_COMP进行页面分配时,分配函数会为每一个增加标志PG_Compound,我们称复合页中的第一个4KB页面为head page,后面的所有page 为tail page。每个page的private保存一个指针,head page的private指向本身,tail page的private指向head page。

  Page页中的flag标记用来识别复合页。在复合页中,打头的第一个普通页成为“head page”,用PG_head标记,而后面的所有页被称为“tail pages”,用PG_tail标记。在64位系统中,可以有多余的标记来表示复合页的页头和页尾;但是在32位系统中却没有那么多的标记,因此采用了一种复用其他标记的方案,即将复合页中的所有页都用PG_compound标记,然后,对于尾页同时也使用PG_reclaim标记,这是因为PG_reclaim只有在页缓存中会用到,而复合页根本就不会在页缓存中使用。

 //32位系统中的标记实例: 
1 #define PG_head_mask ((1L << PG_compound))
2 #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
3
4 static inline int PageHead(struct page *page)
5 {
6 return ((page->flags & PG_head_tail_mask) == PG_head_mask);
7 }
8
9
10 static inline int PageTail(struct page *page)
11 {
12 return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);
13 }

3、复合页的检测:

  可以使用PageCompound函数来检测一个页是否是复合页,另外函数PageHead和函数PageTail用来检测一个页是否是页头或者页尾。在每个尾页的page结构体中都包含一个指向头页的指针 - first_page,可以使用compound_head函数获得。

 

4、复合页的释放:

  那么当一个复合页不再被系统使用时,我们如何知道该复合页包含多少个普通页,又如何知道该复合页的析构函数(destructor)存在哪里呢?首先,人们可能会认为这些信息存在于头页的page结构体中,但是很不幸,在这个结构体中已经没有可用的空间了。因此,这些信息全部存储在第一个尾页的lru字段中,将该复合页的大小(order)首先强制转换为指针类型,然后存储在lru.prev中,将析构函数存储在lru.next中。

 1 static void free_compound_page(struct page *page)
2 {
3 __free_pages_ok(page, compound_order(page));
4 }
5
6 static inline int compound_order(struct page *page)
7 {
8 if (!PageHead(page))
9 return 0;
10 return (unsigned long)page[1].lru.prev;
11 }

  这里就解释了为什么复合页必须至少是两个页。在内核中生成了两个复合页的析构函数,默认情况下会调用free_compound_page来将所有的页返回给系统的页框分配器,而hugetlbfs子系统会调用free_huge_page来做一些统计并释放。使用复合页的最经典的一个例子就是THP(transparent huge page),

linux 复合页( Compound Page )的介绍的更多相关文章

  1. 复合页( Compound Page )

    复合页(Compound Page)就是将物理上连续的两个或多个页看成一个      独立的大页,它能够用来创建hugetlbfs中使用的大页(hugepage).      也能够用来创建透明大页( ...

  2. 大页(Huge Page)简单介绍

    x86(包括x86-32和x86-64)架构的CPU默认使用4KB大小的内存页面(getconf PAGESIZE),但是它们也支持较大的内存页,如x86-64系统就支持2MB大小的大页(huge p ...

  3. Linux内存管理 (11)page引用计数

    专题:Linux内存管理专题 关键词:struct page._count._mapcount.PG_locked/PG_referenced/PG_active/PG_dirty等. Linux的内 ...

  4. 【原创】(十四)Linux内存管理之page fault处理

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  5. 为什么Linux默认页大小是4KB

    本文转载自为什么 Linux 默认页大小是 4KB 导语 我们都知道 Linux 会以页为单位管理内存,无论是将磁盘中的数据加载到内存中,还是将内存中的数据写回磁盘,操作系统都会以页面为单位进行操作, ...

  6. [转载]linux段页式内存管理技术

    原始博客地址: http://blog.csdn.net/qq_26626709/article/details/52742470 一.概述 1.虚拟地址空间 内存是通过指针寻址的,因而CPU的字长决 ...

  7. [转帖] 学习 Linux 大页的内存知识

    一.在解释什么情况下需要开启大页和为啥需要开启大页前先了解下Linux下页的相关的知识:以下的内容是基于32位的系统,4K的内存页大小做出的计算1)目录表,用来存放页表的位置,共包含1024个目录en ...

  8. Linux系统中的Page cache和Buffer cache

    Linux系统中的Page cache和Buffer cache Linux中有两个很容易混淆的概念,pagecache和buffercache,首先简单将一些Linux系统下内存的分布,使用free ...

  9. linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客

    linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客 linux中读写锁的rwlock介绍 2013-02-26 13:59:35 分类: C/C++   http://yaro ...

  10. 刨根究底字符编码之七——ANSI编码与代码页(Code Page)

    ANSI编码与代码页(Code Page) 一.ANSI编码 1. 如前所述,在全世界所有国家和民族的文字符号统一编码的Unicode编码方案问世之前,各个国家.民族为了用计算机记录并显示自己的字符, ...

随机推荐

  1. [COCI2015-2016#2] VUDU

    题目传送门 思路 这是一种简单的树状数组解法. 我们设偏移值表示 \(a_i\) 与目标平均数 \(p\) 的差值,显然,一个区间若能满足条件,需要满足此区间的偏移值之和 \(\ge 0\). 看到区 ...

  2. 黑群晖NAS、windows server服务器内网穿透

    推荐一个套件: http://nas.8x6x.com/ 远程速度大概3m每秒,一月10元,很好用. 怎么使用里面有教程,这里暂时不更新. 2022.10.16更新 目前已经卸载了群辉系统,换了win ...

  3. php使用PDO获取结果集的方法

    php使用PDO获取结果集的方法  转载:https://www.jb51.net/article/105797.htm 更新时间:2017年02月16日 11:11:42   作者:水晶依恋     ...

  4. python实现移动二级目录下的文件到一级目录

    python实现移动二级目录下的文件到一级目录 import os import shutil import sys def move_to_work_folder(work_path, cur_pa ...

  5. 记一次 .NET某家装ERP系统 内存暴涨分析

    一:背景 1. 讲故事 前段时间微信上有一位老朋友找到我,说他的程序跑着跑着内存会突然爆高,有时候会下去,有什么会下不去,怀疑是不是某些情况下存在内存泄露,让我帮忙分析一下,其实内存泄露方面的问题还是 ...

  6. CF846E - Chemistry in Berland

    题意:有一颗树,每个点上有 \(b_i\) 东西,从叶子往上的汇率是 \(1:1\),从父亲往下的汇率是 \(k:1\),求能否使每个点的东西都不少于 \(a_i\). 我们发现,从上往下肯定是不划算 ...

  7. K8S 1.20 弃用 Docker 评估之 Docker CLI 的替代产品 nerdctl

    背景 2020 年 12 月初,Kubernetes 在其最新的 Changelog 中宣布,自 Kubernetes 1.20 之后将弃用 Docker 作为容器运行时. 弃用 Docker 带来的 ...

  8. LeetCode-429 N叉树的层次遍历

    来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal著作权归领扣网络所有.商业转载请联 ...

  9. Jmeter 如何把 时间戳 转为 本地时间

    一.引入主题(time) jmeter中,有很多已经封装好的函数,使用这些函数,就能实现某些特定的功能,这对于没有代码基础,或代码基础薄弱的同学来说,是一个非常大的福音. 二.Jmeter把时间戳转为 ...

  10. the default discovery settings are unsuitable for production use at least one of...的解决办法

    解决办法 elasticsearch.yml加上 discovery.type: single-node