linux 复合页( Compound Page )的介绍
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 )的介绍的更多相关文章
- 复合页( Compound Page )
复合页(Compound Page)就是将物理上连续的两个或多个页看成一个 独立的大页,它能够用来创建hugetlbfs中使用的大页(hugepage). 也能够用来创建透明大页( ...
- 大页(Huge Page)简单介绍
x86(包括x86-32和x86-64)架构的CPU默认使用4KB大小的内存页面(getconf PAGESIZE),但是它们也支持较大的内存页,如x86-64系统就支持2MB大小的大页(huge p ...
- Linux内存管理 (11)page引用计数
专题:Linux内存管理专题 关键词:struct page._count._mapcount.PG_locked/PG_referenced/PG_active/PG_dirty等. Linux的内 ...
- 【原创】(十四)Linux内存管理之page fault处理
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- 为什么Linux默认页大小是4KB
本文转载自为什么 Linux 默认页大小是 4KB 导语 我们都知道 Linux 会以页为单位管理内存,无论是将磁盘中的数据加载到内存中,还是将内存中的数据写回磁盘,操作系统都会以页面为单位进行操作, ...
- [转载]linux段页式内存管理技术
原始博客地址: http://blog.csdn.net/qq_26626709/article/details/52742470 一.概述 1.虚拟地址空间 内存是通过指针寻址的,因而CPU的字长决 ...
- [转帖] 学习 Linux 大页的内存知识
一.在解释什么情况下需要开启大页和为啥需要开启大页前先了解下Linux下页的相关的知识:以下的内容是基于32位的系统,4K的内存页大小做出的计算1)目录表,用来存放页表的位置,共包含1024个目录en ...
- Linux系统中的Page cache和Buffer cache
Linux系统中的Page cache和Buffer cache Linux中有两个很容易混淆的概念,pagecache和buffercache,首先简单将一些Linux系统下内存的分布,使用free ...
- linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客
linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客 linux中读写锁的rwlock介绍 2013-02-26 13:59:35 分类: C/C++ http://yaro ...
- 刨根究底字符编码之七——ANSI编码与代码页(Code Page)
ANSI编码与代码页(Code Page) 一.ANSI编码 1. 如前所述,在全世界所有国家和民族的文字符号统一编码的Unicode编码方案问世之前,各个国家.民族为了用计算机记录并显示自己的字符, ...
随机推荐
- 结合ChatGPT体验新必应new bing 的惊喜:这是我第一次使用的感受
前言 最近相信大家都被 ChatGPT 刷屏了,它的爆火大家是有目共睹的,微软的新必应(New Bing) 是结合了比 ChatGPT 更强大的新一代 OpenAI 语言模式,接下来我们一起来&quo ...
- 代码随想录-day1
链表 今天主要是把链表专题刷完了,链表专题的题目不是很难,基本都是考察对链表的操作的理解. 在处理链表问题的时候,我们通常会引入一个哨兵节点(dummy),dummy节点指向原链表的头结点.这样,当我 ...
- windows11 安装跳过互联网验证
按住shift+F10 cmd 输入 OOBE\BYPASSNRO 电脑重启后 出现 跳过得按钮
- PKU2506Tiling
https://blog.csdn.net/Harington/article/details/86612106
- hdu-2544 最短路(SPFA)
SPFA整体过程 1.用一个队列queue支撑. 2.dis[i]表示目前x到i的距离. 3.b[i]表示i是否在q中. 4.清空队列while(q.size()) q.pop();. 5.初始化(把 ...
- vue实现瀑布流
<template> <div id="app"> <ul> <li ref='waterfallItem' v-for="(i ...
- Python中的__new__()方法
1.__new__()至少要有一个参数cls,代表当前类,此参数在实例时由python解释器自动识别, 2.__new__()必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别 ...
- C++容器map、unordered_map、set、unordered_set的区别
1.map: 底层由红黑树实现. Key在红黑树中有序排列,对红黑树进行中序遍历即可得到Key从小到大的排序序列. 使用map可在O(1)的时间复杂度下快速查找到Key. 2.unordered_ma ...
- 微信h5调分享功能
功能背景: 基于微信公众号的h5商城页面,实现特定商品的分享,包括朋友圈和好友分享功能. 代码实现(以vue项目为例): 首先贴上官方开发文档:https://developers.weixin.qq ...
- Dependency Analyzer
Dependency Analyzer idea插件 查找maven依赖 1.Setting---->Plugins------>Dependency Analyzer 2.使用 po ...