为什么 Linux 默认页大小是 “4KB”?
经常看到一些博客在讲 Linux 内存的 PAGE SIZE
时,都会提到 Linux 默认页大小是 4KB。
笔者通过搜索找到了一些与 PAGE SIZE
相关的资料,希望对读者有所帮助。
因为微信不支持外链,建议点击文章底部的“阅读原文”进行阅读。
1、Linux 默认页大小不是 4KB
首先,我们先看看 Linux 默认页大小是 4KB 是否能够成立?
通过 github 以 #define PAGE_SHIFT
为关键字在 linux 仓库进行搜索,可以得到一个 GitHub 搜索结果页 [1]。
很遗憾, GitHub 搜索结果页的第一个结果就不满足题目中的 4KB
要求。
现将第一个结果 linux/arch/openrisc/include/asm/page.h 的部分代码摘录如下 [2]。
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 13
#ifdef __ASSEMBLY__
#define PAGE_SIZE (1 << PAGE_SHIFT)
#else
#define PAGE_SIZE (1UL << PAGE_SHIFT)
在 openrisc
架构下, PAGE SIZE 是 8 Kbyte (2^13)。
2、Linux 默认页大小是对应架构的 MMU 管理的最小值
本结论来自一篇2002年的文章 Multiple Page Size Support in the Linux Kernel [3]。
The Linux kernel currently supports a single user space page size, usually the minimum dictated by the architecture. This paper describes the ongoing modifications to the Linux kernel to allow applications to vary the size of pages used to map their address spaces and to reap the performance benefits associated with the use of large pages.
我们仍然以 openrisc
架构为例,在OpenRISC 1000Architecture Manual 的 8.1 MMU FEATURES [4] 提到 page size
存在3种,最小是 8 Kbyte
。
Three different page sizes:
Level 0 pages (32 Gbyte; only with 64-bit EA) translated with D/I Area Translation Buffer (ATB)
Level 1 pages (16 MByte) translated with D/I Area Translation Buffer (ATB)
Level 2 pages (8 Kbyte) translated with D/I Translation Lookaside Buffer (TLB)
这份数据可以与上一节的 #define PAGE_SHIFT 13
相互印证。
3、x86 架构下,Linux 默认页大小是 4Kb
x86 架构下,Linux 默认页大小是 4Kb 的原因很简单,x86 的 MMU 管理的最小值就是 4k。
数据来源: Virtual Memory and Linux [5]
ARM – 4k
ARM64 – 4k or 64k
MIPS – Widely Configurable
x86 – 4k
4、Linux 的默认大小会控制在 16K 以内
本结论来自一篇 Linus Torvalds 的吐槽文章 Some alternatives for alias handling [6]。
4kB is good. 8kB is borderline ok. 16kB or more is simply not acceptable.
参考文章
- https://github.com/search?l=C&q=%23define+PAGE_SHIFT+repo%3Atorvalds%2Flinux+path%3Aarch&type=Code
- https://github.com/torvalds/linux/blob/5b8b9d0c6d0e0f1993c6c56deaf9646942c49d94/arch/openrisc/include/asm/page.h#L21
- https://www.kernel.org/doc/ols/2002/ols2002-pages-573-593.pdf
- https://openrisc.io/or1k.html#__RefHeading__504779_595890882
- https://elinux.org/images/4/4c/Ott.pdf
- https://www.realworldtech.com/forum/?threadid=144991&curpostid=145006
- 简陋的swift carthage copy-frameworks 辅助脚本
- 【自问自答】关于 Swift 的几个疑问
- 高级PHP应用程序漏洞审核技术【一】
- 【读书笔记】The Swift Programming Language (Swift 4.0.3)
- Ubuntu 下mysql常用操作
- JDK1.8源码(五)——java.util.ArrayList 类
- 代码审计入门总结
- ubuntu mysql启动|停止|重启
- JDK1.8源码(四)——java.util.Arrays 类
- JDK1.8源码(三)——java.lang.String 类
- JDK1.8源码(二)——java.lang.Integer 类
- Java关键字——instanceof
- 【强势推荐】一款可扫描CVE的工具
- Java的深拷贝和浅拷贝
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 尤大 3 天前发在 GitHub 上的 vue-lit 是啥?
- BFE.dev前端刷题 23. 实现一个sum()方法
- 彻底深刻理解js原型链之prototype,proto以及constructor(一)
- SAP Spartacus取cart的HTTP请求
- 记一次Netty连接池FixedChannelPool连接未释放问题的排查总结
- 神经网络中的蒸馏技术,从Softmax开始说起
- NullInjectorError R3InjectorError(AppModule)[StoreFeatureModule]
- Angular module加载的原理研究
- NullInjectorError No provider for EffectsRootModule!
- Web 中文字体性能优化实践
- Java反射到底慢在哪?不看后悔
- win10 edge 打开闪退问题
- dotnet Open XML 如何判断一份 Office 文档是否被加密
- 【项目实战】ETL 数据导入
- asp dotnet core 记一次应用拒绝响应调试 开启线程等待同步用光线程池