From 6758e5d64486d6d9e106e5d5d019abf41e4c662e Mon Sep 17 00:00:00 2001 From: Cheng Jian Date: Wed, 19 May 2021 19:38:23 +0800 Subject: [PATCH] description: update --- study/kernel/00-DESCRIPTION/DEBUGGING.md | 77 +++++++++ study/kernel/00-DESCRIPTION/KVM.md | 74 +++++++++ study/kernel/00-DESCRIPTION/LIVE_PATCH.md | 0 study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md | 155 ++++++++++-------- study/kernel/00-DESCRIPTION/SCHEDULER.md | 4 + .../images/0002-1-readahead_page_cache.gif | Bin 0 -> 13041 bytes .../images/0002-2-readahead_algorithm.gif | Bin 0 -> 13986 bytes 7 files changed, 245 insertions(+), 65 deletions(-) create mode 100644 study/kernel/00-DESCRIPTION/DEBUGGING.md create mode 100644 study/kernel/00-DESCRIPTION/KVM.md mode change 100755 => 100644 study/kernel/00-DESCRIPTION/LIVE_PATCH.md create mode 100644 study/kernel/00-DESCRIPTION/images/0002-1-readahead_page_cache.gif create mode 100644 study/kernel/00-DESCRIPTION/images/0002-2-readahead_algorithm.gif diff --git a/study/kernel/00-DESCRIPTION/DEBUGGING.md b/study/kernel/00-DESCRIPTION/DEBUGGING.md new file mode 100644 index 0000000..87cb13d --- /dev/null +++ b/study/kernel/00-DESCRIPTION/DEBUGGING.md @@ -0,0 +1,77 @@ +--- + +title: Linux 内核历史的 Git 记录 +date: 2021-02-15 00:32 +author: gatieme +tags: + - linux + - tools +categories: + - 技术积累 +thumbnail: +blogexcerpt: FZF 是目前最快的模糊搜索工具. 使用golang编写. 结合其他工具(比如 ag 和 fasd)可以完成非常多的工作. 前段时间, 有同事给鄙人推荐了 FZF, 通过简单的配置, 配合 VIM/GIT 等工具食用, 简直事半功倍, 效率指数级提升, 因此推荐给大家. + +--- + +
+ +本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 + +知识共享许可协议 + +因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 鄙人在此谢谢啦 + +**转载请务必注明出处, 谢谢, 不胜感激** + +
+ +| 日期 | 作者 | GitHub| CSDN | BLOG | +| ------- |:-------:|:-------:|:-------:|:-------:| +| 2021-02-15 | [成坚-gatieme](https://kernel.blog.csdn.net) | [`AderXCoding/system/tools/fzf`](https://github.com/gatieme/AderXCoding/tree/master/system/tools/fzf) | [使用模糊搜索神器 FZF 来提升办公体验](https://blog.csdn.net/gatieme/article/details/113828826) | [Using FZF to Improve Productivit](https://oskernellab.com/2021/02/15/2021/0215-0001-Using_FZF_to_Improve_Productivity)| + + +
+ +2 **调测子系统** +===================== + + + + +**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 重要功能和时间点 -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*** + + + + + +下文将按此目录分析 Linux 内核中 MM 的重要功能和引入版本: + + + + +**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 正文 -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*** + + + +# 1 UNWIND +------- + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2018/11/23 | Shile Zhang | [Speed booting by sorting ORC unwind tables at build time](https://lore.kernel.org/patchwork/cover/1162315) | ORC unwind有两个表,.orc_unwind_ip和.orc_unwind 二分搜索需要排序。在构建时对其进行排序可以节省更多CPU周期有助于加快内核引导. 添加ORC表排序在一个独立的线程有助于避免更多的链接. | RFC v6 ☐ | [PatchWork v6](https://lore.kernel.org/patchwork/cover/1162315) | + + +相关的文章介绍: [47]. + + + +
+ +* 本作品/博文 ( [AderStep-紫夜阑珊-青伶巷草 Copyright ©2013-2017](http://blog.csdn.net/gatieme) ), 由 [成坚(gatieme)](http://blog.csdn.net/gatieme) 创作. + +* 采用知识共享许可协议知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) ( 包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的. + +* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问, 请与我联系. + +* **转载请务必注明出处, 谢谢, 不胜感激** +
diff --git a/study/kernel/00-DESCRIPTION/KVM.md b/study/kernel/00-DESCRIPTION/KVM.md new file mode 100644 index 0000000..eb762c8 --- /dev/null +++ b/study/kernel/00-DESCRIPTION/KVM.md @@ -0,0 +1,74 @@ +--- + +title: 虚拟化 & KVM 子系统 +date: 2021-02-15 00:32 +author: gatieme +tags: + - linux + - tools +categories: + - 技术积累 +thumbnail: +blogexcerpt: 虚拟化 & KVM 子系统 + +--- + +
+ +本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 + +知识共享许可协议 + +因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 鄙人在此谢谢啦 + +**转载请务必注明出处, 谢谢, 不胜感激** + +
+ +| 日期 | 作者 | GitHub| CSDN | BLOG | +| ------- |:-------:|:-------:|:-------:|:-------:| +| 2021-02-15 | [成坚-gatieme](https://kernel.blog.csdn.net) | [`AderXCoding/system/tools/fzf`](https://github.com/gatieme/AderXCoding/tree/master/system/tools/fzf) | [使用模糊搜索神器 FZF 来提升办公体验](https://blog.csdn.net/gatieme/article/details/113828826) | [Using FZF to Improve Productivit](https://oskernellab.com/2021/02/15/2021/0215-0001-Using_FZF_to_Improve_Productivity)| + + +
+ +2 **虚拟化子系统** +===================== + + + + +**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 重要功能和时间点 -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*** + + + + + +下文将按此目录分析 Linux 内核中 MM 的重要功能和引入版本: + + + + +**-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 正文 -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*** + + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2018/11/23 | Shile Zhang | [Speed booting by sorting ORC unwind tables at build time](https://lore.kernel.org/patchwork/cover/1162315) | ORC unwind有两个表,.orc_unwind_ip和.orc_unwind 二分搜索需要排序。在构建时对其进行排序可以节省更多CPU周期有助于加快内核引导. 添加ORC表排序在一个独立的线程有助于避免更多的链接. | RFC v6 ☐ | [PatchWork v6](https://lore.kernel.org/patchwork/cover/1162315) | + + +相关的文章介绍: [47]. + + + +
+ +* 本作品/博文 ( [AderStep-紫夜阑珊-青伶巷草 Copyright ©2013-2017](http://blog.csdn.net/gatieme) ), 由 [成坚(gatieme)](http://blog.csdn.net/gatieme) 创作. + +* 采用知识共享许可协议知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) ( 包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的. + +* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问, 请与我联系. + +* **转载请务必注明出处, 谢谢, 不胜感激** +
diff --git a/study/kernel/00-DESCRIPTION/LIVE_PATCH.md b/study/kernel/00-DESCRIPTION/LIVE_PATCH.md old mode 100755 new mode 100644 diff --git a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md index d3b7cd8..4f1b403 100755 --- a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md +++ b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md @@ -626,6 +626,33 @@ Linux 一开始是在一台i386上的机器开发的, i386 的硬件页表是2 当 MM 遭遇内存分配紧张时, 会回收页面. **页框替换算法(Page Frame Replacement Algorithm, 下称PFRA)** 的实现好坏对性能影响很大: 如果选中了频繁或将马上要用的页, 将会出现 **Swap Thrashing** 现象, 即刚换出的页又要换回来, 现象就是系统响应非常慢 + + +教科书式的 PFRA 会提到要用 LRU (Least-Recently-Used) 算法, 该算法思想基于 : 最近很少使用的页, 在紧接着的未来应该也很少使用, 因此, 它可以被当作替换掉的候选页. + +但现实中, 要跟踪每个页的使用情况, 开销不是一般的大, 尤其是内存大的系统. 而且, 还有一个问题, LRU 考量的是近期的历史, 却没能体现页面的使用频率 - 假设有一个页面会被多次访问, 最近一次访问稍久点了, 这时涌入了很多只会使用一次的页(比如在播放电影), 那么按照 LRU 语义, 很可能被驱逐的是前者, 而不是后者这些不会再用的页面. + +为此, Linux 引入了两个链表, 一个 active list, 一个 inactive list , 这两个链表如此工作: + +> **1\.** inactive list 链表尾的页将作为候选页, 在需要时被替换出系统. +> **2\.** 对于文件缓存页, 当第一次被读入时, 将置于 inactive list 链表头. 如果它被再次访问, 就把它提升到 active list 链表尾; 否则, 随着新的页进入, 它会被慢慢推到 inactive list 尾巴; 如果它再一次访问, 就把它提升到 active list 链表头. +> **3.** 对于匿名页, 当第一次被读入时, 将置于 active list 链表尾(对匿名页的优待是因为替换它出去要写入交换设备, 不能直接丢弃, 代价更大); 如果它被再次访问, 就把它提升到 active list 链表头, +> **4\.** 在需要换页时, MM 会从 active 链表尾开始扫描, 把足够量页面降级到 inactive 链表头, 同样, 默认文件缓存页会受到优待(用户可通过 **_swappiness_** 这个用户接口设置权重). + + +如上, 上述两个链表按照使用的热度构成了四个层级: + +active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐者) + + + +这种增强版的 LRU 同时考虑了 LRU 的语义: 更近被使用的页在链表头; + +又考虑了使用频度: 还是考虑前面的例子, 一个频繁访问的页, 它极有可能在 active 链表头, 或者次一点, 在 active 链表尾, 此时涌入的大量一次性文件缓存页, 只会被放在 inactive 链表头, 因而它们会更优先被替换出去. + +https://lore.kernel.org/patchwork/patch/222042/ +https://github.com/hakavlad/le9-patch + ### 2.4.1.1 经典地 LRU 算法 ------- @@ -686,10 +713,10 @@ aaba9265318 [PATCH] make pagemap_lru_lock irq-safe | 8 | 2002/08/14 | Andrew Morton | [44260240ce0 ("deferred and batched addition of pages to the LRU")](https://github.com/gatieme/linux-history/commit/44260240ce0d1e19e84138ac775811574a9e1326) | 1. 通过 pagevec 做缓冲和延迟, lru_cache_add 分批地将页面添加到LRU.
2. 在页面回收代码中, 在开始之前清除本地CPU的缓冲区. 减少页面长时间不驻留在LRU上的可能性.
(可以有 15 * num_cpus 页不在LRU上) | -### 2.4.1.2 per-zone LRU +### 2.4.1.2 zone or node base LRU ------- -(2002/08/27)2.5.33 合入 +2.5.33 合入了基于 zone 的 LRU | 编号 | 时间 | 作者 | 补丁 | 描述 | @@ -698,45 +725,24 @@ aaba9265318 [PATCH] make pagemap_lru_lock irq-safe | 2 | 2002/08/27 | Andrew Morton | [e6f0e61d9ed9 ("per-zone-LRU")](https://github.com/gatieme/linux-history/commit/e6f0e61d9ed94134f57bcf6c72b81848b9d3c2fe) | per zone 的 LRU 替换原来的全局 LRU 链表 | | 3 | 2002/08/27 | Andrew Morton | [a8382cf11536 ("per-zone LRU locking")](https://github.com/gatieme/linux-history/commit/a8382cf1153689a1caac0e707e951e7869bb92e1) | per zone 的 lru_lock 替换原来的全局 `_pagemap_lru_lock` | +4.8 合入了基于 zone 的页面回收策略, 将 LRU 的页面回收从 zone 迁移到了 node 上. + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2016/07/08 | Mel Gorman | [Move LRU page reclaim from zones to nodes v9](https://lore.kernel.org/patchwork/cover/696408) | 实现 SLOB 分配器 | v9 ☑ [4.8](https://kernelnewbies.org/Linux_4.8#Memory_management) | [PatchWork v21](https://lore.kernel.org/patchwork/cover/696408) | -### 2.4.1.1 增强的LRU算法 -------- - -**(2.6前引入, 具体时间难考)** - - -教科书式的 PFRA 会提到要用 LRU (Least-Recently-Used) 算法, 该算法思想基于 : 最近很少使用的页, 在紧接着的未来应该也很少使用, 因此, 它可以被当作替换掉的候选页. - -但现实中, 要跟踪每个页的使用情况, 开销不是一般的大, 尤其是内存大的系统. 而且, 还有一个问题, LRU 考量的是近期的历史, 却没能体现页面的使用频率 - 假设有一个页面会被多次访问, 最近一次访问稍久点了, 这时涌入了很多只会使用一次的页(比如在播放电影), 那么按照 LRU 语义, 很可能被驱逐的是前者, 而不是后者这些不会再用的页面. - -为此, Linux 引入了两个链表, 一个 active list, 一个 inactive list , 这两个链表如此工作: - -> **1\.** inactive list 链表尾的页将作为候选页, 在需要时被替换出系统. -> **2\.** 对于文件缓存页, 当第一次被读入时, 将置于 inactive list 链表头. 如果它被再次访问, 就把它提升到 active list 链表尾; 否则, 随着新的页进入, 它会被慢慢推到 inactive list 尾巴; 如果它再一次访问, 就把它提升到 active list 链表头. -> **3.** 对于匿名页, 当第一次被读入时, 将置于 active list 链表尾(对匿名页的优待是因为替换它出去要写入交换设备, 不能直接丢弃, 代价更大); 如果它被再次访问, 就把它提升到 active list 链表头, -> **4\.** 在需要换页时, MM 会从 active 链表尾开始扫描, 把足够量页面降级到 inactive 链表头, 同样, 默认文件缓存页会受到优待(用户可通过 **_swappiness_** 这个用户接口设置权重). - - -如上, 上述两个链表按照使用的热度构成了四个层级: - -active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐者) - - - -这种增强版的 LRU 同时考虑了 LRU 的语义: 更近被使用的页在链表头; - -又考虑了使用频度: 还是考虑前面的例子, 一个频繁访问的页, 它极有可能在 active 链表头, 或者次一点, 在 active 链表尾, 此时涌入的大量一次性文件缓存页, 只会被放在 inactive 链表头, 因而它们会更优先被替换出去. - +[memcg lru lock 血泪史](https://blog.csdn.net/bjchenxu/article/details/112504932) +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2020/12/05 | Alex Shi | [per memcg lru lock](https://lore.kernel.org/patchwork/cover/1333353) | 实现 SLOB 分配器 | v21 ☑ [5.11](https://kernelnewbies.org/Linux_5.11#Memory_management) | [PatchWork v21](https://lore.kernel.org/patchwork/cover/1333353) | ### 2.4.1.2 active 与 inactive 链表拆分 ------- **2.6.28(2008年12月)** - - 4.1 中描述过一个用户可配置的接口 : **_swappiness_**. 这是一个百分比数(取值 0 -100, 默认60), 当值越靠近100, 表示更倾向替换匿名页; 当值越靠近0, 表示更倾向替换文件缓存页. 这在不同的工作负载下允许管理员手动配置. @@ -749,6 +755,7 @@ active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐 | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| | 2.4.0-test9pre1 | Rik van Riel | [MM balancing (Rik Riel)](https://github.com/gatieme/linux-history/commit/1fc53b2209b58e786c102e55ee682c12ffb4c794) | 引入 MM balancing, 其中将 LRU 拆分成了 active_list 和 inactive_dirty_list 两条链表 | 2.4.0-test9pre1 | [1fc53b2209b](https://github.com/gatieme/linux-history/commit/1fc53b2209b58e786c102e55ee682c12ffb4c794) | +| 2002/10/31 | Andrew Morton | [MM balancing (Rik Riel)](https://github.com/gatieme/linux-history/commit/1fc53b2209b58e786c102e55ee682c12ffb4c794) | 优化高压力 SWAP 下的性能, 为了防止匿名页过早的被释放, 在匿名页创建后先将他们加入到 active LRU list. | 2.5.46 | [HISTORY COMMIT1 228c3d15a70](https://github.com/gatieme/linux-history/commit/228c3d15a7020c3587a2c356657099c73f9eb76b)
*-*-*-*-*-*-*-*
[HISTORY COMMIT2 33709b5c802](https://github.com/gatieme/linux-history/commit/33709b5c8022486197ed2345eed18bbeb14a2251)
*-*-*-*-*-*-*-*
[HISTORY COMMIT3 a5bef68d6c8](https://github.com/gatieme/linux-history/commit/a5bef68d6c85d26344dd31b4c342e5a365e68326)
*-*-*-*-*-*-*-*
| | 2007/03/16 | Rik van Riel | [split file and anonymous page queues](https://lore.kernel.org/patchwork/cover/76770) | 将 LRU 中匿名页和文件页拆分的第一次尝试 | RFC v3 ☐ | [PatchWork RFC v1](https://lore.kernel.org/patchwork/cover/76719)
*-*-*-*-*-*-*-*
[PatchWork RFC v2](https://lore.kernel.org/patchwork/cover/76558)
*-*-*-*-*-*-*-*
[PatchWork RFC v3](https://lore.kernel.org/patchwork/cover/76558) | | 2007/11/03 | Rik van Riel | [split anon and file LRUs](https://lore.kernel.org/patchwork/cover/96138) | 将 LRU 中匿名页和文件页分开管理的系列补丁 | RFC ☐ | [PatchWork RFC](https://lore.kernel.org/patchwork/cover/96138) | | 2008/06/11 | Rik van Riel | [VM pageout scalability improvements (V12)](https://lore.kernel.org/patchwork/cover/118967) | 一系列完整的重构和优化补丁, 在大内存系统上, 扫描 LRU 中无法(或不应该)从内存中逐出的页面. 它不仅会占用CPU时间, 而且还会引发锁争用. 并且会使大型系统处于紧张的内存压力状态. 该补丁系列通过一系列措施提高了虚拟机的可扩展性:
1. 将文件系统支持的、交换支持的和不可收回的页放到它们自己的LRUs上, 这样系统只扫描它可以/应该从内存中收回的页
@@ -785,8 +792,6 @@ active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐 **2.6.31(2009年9月发布)** - - 试想, 当你在拷贝一个非常大的文件时, 你发现突然电脑变得反应慢了, 那么可能发生的事情是: 突然涌入的大量文件缓存页让内存告急, 于是 MM 开始扫描前面说的链表, 如果系统的设置是倾向替换文件页的话(**_swappiness_** 靠近0), 那么很有可能, 某个 C 库代码所在代码要在这个内存吃紧的时间点(意味扫描 active list 会比较凶)被挑中, 给扔掉了, 那么程序执行到了该代码, 要把该页重新换入, 这就是发生了前面说的 **Swap Thrashing** 现象了. 这体验自然就差了. @@ -796,7 +801,7 @@ active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐 解决方法是在扫描这些在使用中的代码文件缓存页时, 跳过它, 让它有多一点时间待在 active 链表上, 从而避免上述问题. [22](#refer-anchor-22), [23](#refer-anchor-23) -## 2.4.1.5 工作集大小的探测 +## 2.4.1.5 工作集大小的探测(Better active/inactive list balancing) ------- **3.15(2014年6月发布)** @@ -805,9 +810,6 @@ active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐 一个文件缓存页(代码)一开始进入 inactive 链表表头, 如果它没被再次访问, 它将被慢慢推到 inactive 链表表尾, 最后在回收时被回收走; 而如果有再次访问, 它会被提升到 active 链表尾, 再再次访问, 提升到 active 链表头. 因此, 可以定义一个概念: **访问距离, 它指该页面第一次进入内存到被踢出的间隔, 显然至少是 inactive 链表的长度.** - - - **那么问题来了: 这个 inactive 链表的长度得多长? 才能保护该代码页在第二次访问前尽量不被踢出, 以避免 Swap Thrashing 现象.** @@ -816,32 +818,19 @@ active 头(热烈使用中) > active 尾 > inactive 头 > inactive 尾(被驱逐 -3.15 就引入了一种算法, 它通过估算访问距离, 来测定工作集的大小, 从而维持 inactive 链表在一个合适长度[24](#refer-anchor-24). +在 v3.15 时 Johannes Weiner 引入了一种 [Refault Distance 算法](https://lwn.net/Articles/495543), 它通过估算访问距离, 来测定工作集的大小, 从而维持 inactive 链表在一个合适长度. 最早 v3.15 合入时, 只针对页面高速缓存类型的页面生效. 随后被不断优化. -### 2.4.1.6 node-based LRU reclaim -------- -之前版本的 LRU 链表都是按照 zone 来管理和配置的, 4.8 合入了基于 zone 的页面回收策略, 将 LRU 的页面回收从 zone 迁移到了 node 上. | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| -| 2016/07/08 | Mel Gorman | [Move LRU page reclaim from zones to nodes v9](https://lore.kernel.org/patchwork/cover/696408) | 实现 SLOB 分配器 | v9 ☑ [4.8](https://kernelnewbies.org/Linux_4.8#Memory_management) | [PatchWork v21](https://lore.kernel.org/patchwork/cover/696408) | +| 2014/04/03 | Johannes Weiner | [mm: thrash detection-based file cache sizing v9](https://lwn.net/Articles/495543) | 引入基于 Refault Distance 算法的文件高速缓存页的工作集探测 | v9 ☑ [3.15](https://kernelnewbies.org/Linux_3.15#head-dbe2430cd9e5ed1d3f2362367758cd490aba4b9d) | [PatchWork v9](https://lore.kernel.org/patchwork/cover/437949) | +| 2018/08/28 | Johannes Weiner | [psi: pressure stall information for CPU, memory, and IO v4](https://lore.kernel.org/patchwork/cover/978495) | NA | v1 ☑ [4.20-rc1](https://kernelnewbies.org/Linux_4.20#Memory_management) | [PatchWork](https://lore.kernel.org/patchwork/cover/978495) | +| 2018/10/09 | Johannes Weiner | [mm: workingset & shrinker fixes](https://lore.kernel.org/patchwork/cover/997829) | NA | v1 ☑ [4.20-rc1](https://kernelnewbies.org/Linux_4.20#Memory_management) | [PatchWork](https://lore.kernel.org/patchwork/cover/997829) | +| 2020/04/03 | Joonsoo Kim | [workingset protection/detection on the anonymous LRU list](https://lwn.net/Articles/815342) | 实现对匿名 LRU 页面列表的工作集保护和检测. 在之前的实现中, 新创建的或交换中的匿名页, 都是默认加入到 active LRU list, 然后逐渐降级到 inactive LRU list. 这造成在某种场景下新申请的内存(即使被使用一次cold page)也会把在a ctive list 的 hot page 挤到 inactive list. 为了解决这个的问题, 这组补丁, 将新创建或交换的匿名页面放到 inactive LRU list 中, 只有当它们被足够引用时才会被提升到活动列表. 另外, 因为这些更改可能导致新创建的匿名页面或交换中的匿名页面交换不活动列表中的现有页面, 所以工作集检测被扩展到处理匿名LRU列表. 以做出更优的决策 | v5 ☑ [5.9-rc1](https://kernelnewbies.org/Linux_5.9#Memory_management) | [PatchWork v5](https://lore.kernel.org/patchwork/cover/1219942), [Patchwork v7](https://lore.kernel.org/patchwork/patch/1278082), [ZhiHu](https://zhuanlan.zhihu.com/p/113220105) | -### 2.4.1.6 per memcg lru lock -------- - -[memcg lru lock 血泪史](https://blog.csdn.net/bjchenxu/article/details/112504932) - -| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | -|:----:|:----:|:---:|:----:|:---------:|:----:| -| 2020/12/05 | Alex Shi | [per memcg lru lock](https://lore.kernel.org/patchwork/cover/1333353) | 实现 SLOB 分配器 | v21 ☑ [5.11](https://kernelnewbies.org/Linux_5.11#Memory_management) | [PatchWork v21](https://lore.kernel.org/patchwork/cover/1333353) | - - - -https://lore.kernel.org/patchwork/patch/222042/ -https://github.com/hakavlad/le9-patch ## 2.4.2 madvise MADV_FREE 页面延迟回收 @@ -949,28 +938,60 @@ Linux 内核在脏页数量到达一定门槛时, 或者用户在命令行输入 > **2\.** 平缓地修改扼制的门槛. 之前进程被罚的门槛会随着一个重量级进程的启动而走人骤降, 在吴峰光的算法中, 增加了对全局内存压力的评估, 从而平滑地修改这一门槛. > **3\.** 在进程生成脏页的扼制方面, 吴峰光同样采取反馈调节的做法, 针对写回工作量和写回速度, 平缓地(尽量)把系统的脏页生成控制在定点附近. + +## 2.5.4 MEMCG DRITY Page +------- + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2011/04/17 | Greg Thelen | [memcg: per cgroup dirty page limiting](https://lore.kernel.org/patchwork/cover/263368) | per-memcg 的脏页带宽限制 | v9 ☐ | [PatchWork v9](https://lore.kernel.org/patchwork/cover/263368) | +| 2015/12/30 | Tejun Heo | [memcg: add per cgroup dirty page accounting](https://lore.kernel.org/patchwork/cover/558382) | madvise 支持页面延迟回收(MADV_FREE)的早期尝试 | v5 ☑ [4.2-rc1](https://kernelnewbies.org/Linux_4.2#Memory_management) | [PatchWork v1](https://lore.kernel.org/patchwork/cover/558382), [commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c4843a7593a9df3ff5b1806084cefdfa81dd7c79) | + + # 2.6 页面预读 ------- +[linux文件预读发展过程](https://blog.csdn.net/jinking01/article/details/106541116) 从用户角度来看, 这一节对了解 Linux 内核发展帮助不大, 可跳过不读; 但对于技术人员来说, 本节可以展现教材理论模型到工程实现的一些思考与折衷, 还有软件工程实践中由简单粗糙到复杂精细的演变过程 - - - 系统在读取文件页时, 如果发现存在着顺序读取的模式时, 就会预先把后面的页也读进内存, 以期之后的访问可以快速地访问到这些页, 而不用再启动快速的磁盘读写. -## 2.6.1 原始的预读方案 (时间很早, 未可考) +## 2.6.1 原始的预读框架 ------- +Linux内核的一大特色就是支持最多的文件系统, 并拥有一个虚拟文件系统(VFS)层. 早在2002年, 也就是2.5内核的开发过程中, Andrew Morton在VFS层引入了文件预读的基本框架, 以统一支持各个文件系统. 如图所示, Linux内核会将它最近访问过的文件页面缓存在内存中一段时间, 这个文件缓存被称为pagecache. 如下图所示. 一般的read()操作发生在应用程序提供的缓冲区与pagecache之间. 而预读算法则负责填充这个 pagecache. 应用程序的读缓存一般都比较小, 比如文件拷贝命令cp的读写粒度就是4KB;内核的预读算法则会以它认为更合适的大小进行预读I/O, 比比如16-128KB. + + +![以pagecache为中心的读和预读](./images/0002-1-readahead_page_cache.gif) + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2002/04/09 | Andrew Morton | [readahead](https://github.com/gatieme/linux-history/commit/8fa498462272fec2c16a92a9a7f67d005225b640) | 统一的预读框架, 预读算法的雏形 | v1 ☑ 2.5.8 | [HISTORY commit](https://github.com/gatieme/linux-history/commit/8fa498462272fec2c16a92a9a7f67d005225b640) | +| 2003/02/03 | Andrew Morton | [implement posix_fadvise64()](https://github.com/gatieme/linux-history/commit/fccbe3844c29beed4e665b1a5aafada44e133adc) | 引入 posix_fadvise64 | v1 ☑ 2.5.60 | [HISTORY commit](https://github.com/gatieme/linux-history/commit/fccbe3844c29beed4e665b1a5aafada44e133adc) | + + +## 2.6.2 预读算法及其优化 +------- 一开始, 内核的预读方案如你所想, 很简单. 就是在内核发觉可能在做顺序读操作时, 就把后面的 128 KB 的页面也读进来. +大约一年之后, Linus Torvalds 把 mmap 缺页 I/O 的预取算法单独列出, 从而形成了 read-around/read-ahead 两个独立算法(图4). read-around算法适用于那些以mmap方式访问的程序代码和数据, 它们具有很强的局域性(locality of reference)特征. 当有缺页事件发生时, 它以当前页面为中心, 往前往后预取共计128KB页面. 而readahead算法主要针对read()系统调用, 它们一般都具有很好的顺序特性. 但是随机和非典型的读取模式也大量存在, 因而readahead算法必须具有很好的智能和适应性. + +![Linux中的read-around, read-ahead和direct read](./images/0002-2-readahead_algorithm.gif) + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2003/07/03 | Linus Torvalds | [Simplify and speed up mmap read-around handling](https://github.com/gatieme/linux-history/commit/82a333fa1948869322f32a67223ea8d0ae9ad8ba) | 引入 posix_fadvise64 | v1 ☑ 2.5.75 | [HISTORY commit](https://github.com/gatieme/linux-history/commit/82a333fa1948869322f32a67223ea8d0ae9ad8ba) | +| 2005/01/03 | Steven Pratt , Ram Pai | [Simplified readahead](https://github.com/gatieme/linux-history/commit/6f734a1af323ab4690610ecd575198ae219b6fe8) | 引入读大小参数, 代码简化及优化; 支持随机读. | v1 ☑ 2.6.11 | [HISTORY commit 1](https://github.com/gatieme/linux-history/commit/6f734a1af323ab4690610ecd575198ae219b6fe8), [HISTORY commit 2](250c01d06ccb125519cc9958d938f41736868be9) | +| 2005/03/07 | Oleg Nesterov | [readahead: improve sequential read detection](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=671ccb4b50a6ef21e8c0ed0ef9070098295e1e61) | 支持非对齐顺序读. | v1 ☑ [2.6.12](https://kernelnewbies.org/Linux_2_6_12) | [commit 1](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=671ccb4b50a6ef21e8c0ed0ef9070098295e1e61), [commit 2](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=577a3dd8fd68d24056075fdf479a1627586f8c46) | + ## 2.6.2 按需预读(On-demand Readahead) @@ -979,19 +1000,23 @@ Linux 内核在脏页数量到达一定门槛时, 或者用户在命令行输入 **2.6.23(2007年10月发布)** - - 这种固定的128 KB预读方案显然不是最优的. 它没有考虑系统内存使用状况和进程读取情况. 当内存紧张时, 过度的预读其实是浪费, 预读的页面可能还没被访问就被踢出去了. 还有, 进程如果访问得凶猛的话, 且内存也足够宽裕的话, 128KB又显得太小家子气了. +后续通过 Steven Pratt、Ram Pai 等人的大量工作, readahead算法进一步完善. 其中最重要的一点是实现了对随机读的完好支持. 随机读在数据库应用中处于非常突出的地位. 在此之前, 预读算法以离散的读页面位置作为输入, 一个多页面的随机读会触发“顺序预读”. 这导致了预读I/O数的增加和命中率的下降. 改进后的算法通过监控所有完整的 read( )调用, 同时得到读请求的页面偏移量和数量, 因而能够更好的区分顺序读和随机读. - -2.6.23的内核引入了在这个领域耕耘许久的吴峰光的一个按需预读的算法[29](#refer-anchor-29). 所谓的按需预读, 就是内核在读取某页不在内存时, 同步把页从外设读入内存, 并且, 如果发现是顺序读取的话, 还会把后续若干页一起读进来, 这些预读的页叫预读窗口; 当内核读到预读窗口里的某一页时, 如果发现还是顺序读取的模式, 会再次启动预读, 异步地读入下一个预读窗口. +2.6.23的内核引入了在这个领域耕耘许久的吴峰光的一个[按需预读的算法]((https://lwn.net/Articles/235164). 所谓的按需预读, 就是内核在读取某页不在内存时, 同步把页从外设读入内存, 并且, 如果发现是顺序读取的话, 还会把后续若干页一起读进来, 这些预读的页叫预读窗口; 当内核读到预读窗口里的某一页时, 如果发现还是顺序读取的模式, 会再次启动预读, 异步地读入下一个预读窗口. 该算法关键就在于适当地决定这个预读窗口的大小,和哪一页做为异步预读的开始. 它的启发式逻辑也非常简单, 但取得不了错的效果. 此外, 对于两个进程在同一个文件上的交替预读, 2.6.24 增强了该算法, 使其能很好地侦测这一行为. +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2005/10/06 | WU Fengguang | [Adaptive file readahead](https://lwn.net/Articles/155510) | 自适应预读算法 | v1 ☐ | [LWN](https://lwn.net/Articles/155097) | +| 2011/05/17 | WU Fengguang | [512K readahead size with thrashing safe readahead](https://lwn.net/Articles/372384) | 将每次预读窗口大小的最大值从 128KB 增加到了 512KB, 其中增加了一个统计接口(tracepoint, stat 节点等). | v3 ☐ | [PatchWork](https://lore.kernel.org/patchwork/cover/190891), [LWN](https://lwn.net/Articles/234784) | +| 2011/05/17 | WU Fengguang | [on-demand readahead](https://lwn.net/Articles/235164) | on-demand 预读算法 | v1 ☑ [2.6.23-rc1](https://kernelnewbies.org/Linux_2_6_23#On-demand_read-ahead) | [LWN](https://lwn.net/Articles/234784) | + # 2.7 大内存页支持 ------- @@ -1092,7 +1117,7 @@ https://lore.kernel.org/patchwork/cover/1118785 [linux内存管理-反向映射](https://blog.csdn.net/faxiang1230/article/details/106609834) -[如何知道物理内存中的某个页帧属于某个进程,或者说进程的某个页表项?](https://www.zhihu.com/question/446137543) +[如何知道物理内存中的某个页帧属于某个进程, 或者说进程的某个页表项?](https://www.zhihu.com/question/446137543) RMAP 反向映射是一种物理地址反向映射虚拟地址的方法. diff --git a/study/kernel/00-DESCRIPTION/SCHEDULER.md b/study/kernel/00-DESCRIPTION/SCHEDULER.md index 26306fc..afe5036 100755 --- a/study/kernel/00-DESCRIPTION/SCHEDULER.md +++ b/study/kernel/00-DESCRIPTION/SCHEDULER.md @@ -651,6 +651,10 @@ TencentOS-kernel 回合了主线 wake_affine 中几个优化迁移的补丁, 可 关于这方面, 可以看这篇文章: [Scheduling domains [LWN.net]](https://link.zhihu.com/?target=https%3A//lwn.net/Articles/80911/) +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:---:|:----------:|:----:| +| 2009/09/01 | Peter Zijlstra | [load-balancing and cpu_power -v2](https://lore.kernel.org/patchwork/patch/169381) | load balance 感知 CPU PWOER, 对于 RT 任务, 引入了 sched_time_avg 来平均一段时间内实时任务的 CPU 消耗. 用得到的平均值来调整非实时任务的 CPU 功率, 以确保实时任务不必争抢 CPU. | v4 ☑ |[PatchWork](https://lore.kernel.org/patchwork/patch/169381) | + ## 1.5.3 自动 NUMA 均衡(Automatic NUMA balancing) ------- diff --git a/study/kernel/00-DESCRIPTION/images/0002-1-readahead_page_cache.gif b/study/kernel/00-DESCRIPTION/images/0002-1-readahead_page_cache.gif new file mode 100644 index 0000000000000000000000000000000000000000..39434009b105e90a1f68649d24dc17034ba51875 GIT binary patch literal 13041 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 literal 0 HcmV?d00001 diff --git a/study/kernel/00-DESCRIPTION/images/0002-2-readahead_algorithm.gif b/study/kernel/00-DESCRIPTION/images/0002-2-readahead_algorithm.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d6a37bbcfaca442f7d56c59901962fbf17a0a49 GIT binary patch literal 13986 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 W(VuTO6u;%^w||Z7`ON@;rT+(l*I8r$ literal 0 HcmV?d00001