![](https://img-blog.csdnimg.cn/2019092715111047.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
linux.mm
文章平均质量分 61
linux mm
byd yes
这个作者很懒,什么都没留下…
展开
-
swappiness
swappiness的值从0到100不等(默认一般是60),这个值越高,则回收的时候越优先选择anonymous pages。当swappiness等于100的时候,anonymous pages和page cache就具有相同的优先级。至于为什么不从开销最小的角度将swappiness设为0?如果swappiness为0,在内存回收的时候就不会去扫描annoymous page的LRU链表,只适用于page cache很多的场景。...原创 2021-12-30 09:20:38 · 446 阅读 · 0 评论 -
linux缺页异常处理流程图解
原创 2021-12-09 15:41:53 · 637 阅读 · 0 评论 -
vmalloc arm64系统结构和32位体系结构区别
32位体系结构:vmalloc分配内存时,pgd使用的是每个进程的pgd页表(task_struct->mm->pgd),所有在其他进程访问vmalloc分配的内存时会出现访问不到的情况,所以在do_page_fault里面会同步页表64位体系结构:vmalloc分配内存时,pgd直接使用的是内核全局页表swapper_pg_dir(mm_init->pgd)。所以就不存在页表同步问题。归根结底就是32位体系结构的内核空间虚拟地址范围太小了。.........原创 2021-10-29 16:54:31 · 625 阅读 · 0 评论 -
总结内存管理数据结构和API
思考题:请画出内存管理中常用的数据结构的关系图,例如mm_strut、vma、vaddr、page、pfn、pte、zone、paddr和pg_data等,并四号如下转换关系。 如何由mm数据结构和虚拟地址vaddr找打对应的VMA? 如何由page和VMA找到虚拟地址vaddr? 如何由page找到所有映射的VMA? 如何由VMA和虚拟地址vaddr找出相应的page数据结构? page和pfn之间的互换? pfn和paddr之间的互换?原创 2021-07-22 16:37:57 · 580 阅读 · 0 评论 -
18.3 KSM页面小结
核心设计思想是基于写时复制机制COW,也就是内容相同的页面可以合并成一个只读页面,从而释放出来空闲页面。首先要思考怎么去查找,以及合并什么样类型的页面?哪些应用场景会有比较丰富的冗余页面? KSM最早是为了KVM虚拟机也设计的,KVM虚拟机在宿主机上使用的内存大部分是匿名页面,并且它们在宿主机中存在大量的冗余内存。对于典型的应用程序,KSM值考虑进程分配使用的匿名页面,暂时不考虑pagecache的情况。一个典型的应用程序可以由以下5个内存部分组成。 可执行文件的内存映射(page cac...原创 2021-07-22 16:30:12 · 397 阅读 · 2 评论 -
18.2 匿名页面和KSM页面的区别
最后讨论一个有趣的问题:如果多个VMA的虚拟页面同时映射了同一个匿名页面,那么page->index应该等于多少? 虽然匿名页面和KSM页面可以通过PageAnon()和PageKsm()宏来分区。但是这两种页面究竟有什么区别呢?是不是多个VMA的虚拟页面共享一个匿名页面的情况就一定是KSM页面呢?这是一个非常好的问题,可以从中窥探出匿名页面和KSM页面的区别。这个问题要分两种情况,一是父子进程的VMA共享同一个匿名页面,二是不相干的进程VMA共享同一个匿名页面。 (1)第一种情...原创 2021-07-22 16:29:29 · 361 阅读 · 1 评论 -
18.1 KSM实现
KSM在初始化是会创建一个名为"ksmd"的内核线程。[mm/ksm.c]static int __init ksm_init(void){ struct task_struct *ksm_thread; int err; err = ksm_slab_init(); if (err) goto out; ksm_thread = kthread_run(ksm_scan_thread, NULL, "ksmd"); if (I原创 2021-07-21 21:47:32 · 850 阅读 · 0 评论 -
18 KSM
内存资源是计算机中比较宝贵的资源,在系统里的物理页面无时无刻不在循环着重新分配和释放,那么是否会有一些内存页面在它们生命周期某个瞬间页面内容完全一致呢? 在阅读本节前请思考如下小问题。 KSM是基于什么原理来合并页面的? 答:基于写时复制,当两个匿名页面的内容一样的时候,将匿名页面原来的pte设置为写保护,然后pte指向kpage。 在KSM机制里,合并过程中把page设置成写保护的函数write_protect_page()有这样一个判断: if(page_mapco...原创 2021-07-21 21:40:56 · 132 阅读 · 0 评论 -
17.1 内存规整小结
系统长时间运行后,页面变得越来越分散,分配一大块连续的物理内存变得越来越难,但有时系统就是需要一大块连续的物理内存,这就是内存碎片化(memory fragmemtation)带来的问题。内存碎片化是操作系统内存管理的一大难题,系统运行时间越长,则内存碎片化越严重,最直接的影响就是分配大块内存失败。 在linux2.6.24内核中集成了社区专家Mel Gorman的Anti-fragmentation patch,其核心思想是把内存页面按照可移动、可回收、不可移动等特定进程分类。可移动的页面通...原创 2021-07-21 21:40:23 · 176 阅读 · 1 评论 -
17 内存规整(memory compaction)
伙伴系统以页为单位来管理内存,内存碎片也是基于页面的,即有大量离散且不连续的页面导致的。从内存角度来看,内存碎片不是好事情,有些情况下物理设备需要大段的连续的物理内存,如果内核无法满足,则会发生内核panic。内存碎片化好比军训中带队行走时间长了,队列乱了,需要重新规整一下,因此本章称为内存规整,一些文献称为内存紧凑,它是为了解决内存碎片化而出现的一个功能。 内核中去碎片化的基本原理是按照页的可移动性将页面分组。迁移内核本身使用的物理内存的实现难度和复杂度都很大,因此目前的内核是不迁移内核...原创 2021-07-21 21:39:52 · 761 阅读 · 1 评论 -
16 页面迁移
linux为页面迁移提供了一个系统调用migrate_pages,最早是在linux2.6.16版本加入的,它可以迁移一个进程的所有页面到指定内存节点上,该系统调用在用户空间的函数接口如下:#include <numaif.h>long migrate_pages(int pid, unsigned long maxnode, const unsigned long *old_nodes, const unsigned long *new_nodes); 该系统调用最早...原创 2021-07-21 21:35:44 · 632 阅读 · 1 评论 -
15.3 匿名页面的换入和销毁
匿名页面的换入: 匿名页面被换出到swap分区后,如果应用程序需要读写这个页面,缺页中断发送,因为pte中的present比特位显示该页不在内存中,但pte表项不为空,说明该页在swap分区中,因此调用do_swap_page()函数重新读入该页的内容。匿名页面的销毁: 当用户关闭或退出时,会扫描这个用户进程所有的VMAs,并会清除这些VMA上所有的映射,如果符合释放标准,相关页面会被释放。本例中的anon_page只映射了父进程VMA,所以这个页面也会被释放。如下图:...原创 2021-07-21 21:31:08 · 173 阅读 · 0 评论 -
15.2 匿名页面的使用和换出
匿名页面的使用: 匿名页面在缺页中断中分配完成之后,就建立了进程虚拟地址空间VMA和物理页面的映射关系,用户进程访问虚拟地址即访问匿名页面的内容 匿名页面的换出: 假设现在系统内存紧张,需要回收一些页面来释放内存。anon_page刚分配时会加入活跃LRU链表(LRU_ACTIVE_ANON)的头部,在经历了活跃LRU链表的一段时间的移动,该anon_page到达活跃LRU链表的尾部,shrink_active_list()函数把该页加入不活跃LRU链表(LRU_INAC...原创 2021-07-20 22:16:07 · 411 阅读 · 0 评论 -
15.1 匿名页面的诞生
从内核的角度来看,在如下情况会出现匿名页面。 用户空间通过malloc/mmap接口函数来分配内存,在内核空间中发生缺页中断时,do_anonymous_page()会产生匿名页面。 发生写时复制。当缺页中断出现写保护错误时,新分配的页面是匿名页面,下面又分两种情况。 do_wp_page() 只读的special映射的页,例如映射到zero page的页面 非单身匿名页面(有多个映射的匿名页面。即page->_mapcount > 0)。原创 2021-07-20 22:15:32 · 327 阅读 · 0 评论 -
15 匿名页面生命周期
问题: 请简述匿名页面的生命周期。在什么情况下会产生匿名页面?在什么条件下会释放匿名页面? 答: 任何事物都有其固定的生命周期,就像一个企业有创立、成长、成熟、衰退等阶段。匿名页面也是有生命周期的,分为诞生、使用、回收、释放等阶段。我们从生命周期的角度来观察匿名页面,本章将匿名页面简称为anon_page。...原创 2021-07-20 22:14:58 · 111 阅读 · 0 评论 -
14.8 页面回收小结
页面回收是Linux内核内存管理中比较难理解的一部分,因此Linux 4.0内核的页面回收代码仍然基于zone的LRU扫描策略,和页面分配代码(page allocator)搭配产生了复杂的"化学反应"和很多诡异难懂的补丁。 Linux内核页面回收如下图所示:可以看到一个页面如何添加到LRU链表的,如何在活跃LRU链表和不活跃LRU链表中移动的,以及如何让一个页面真正回收并被释放的过程。linux2.4.0和linux4.0版本的比较...原创 2021-07-20 22:14:15 · 110 阅读 · 0 评论 -
14.4 shrink_zone函数
do_wp_page()函数处理那些用户试图修改pte页表没有可写属性的页面,它新分配一个页面并且复制旧页面内容到新的页面中。/* * This routine handles present pages, when users try to write * to a shared page. It is done by copying the page to a new address * and decrementing the shared-page counter for the old原创 2021-07-20 21:57:44 · 614 阅读 · 1 评论 -
14.7 跟踪LRU活动情况和Refault Distance算法
linux内核内存管理的实现以structpage为核心,类似城市的地标(如上海的东方明珠),其他所有的内存管理设施都为之展开,例如VMA管理、缺页中断、反向映射、页面分配与回收等。structpage数据结构定义在include/linux/mm_types.h头文件中,大量使用了C语言的联合体union来优化其数据结构的大小,因为每个物理页面都需要一个structpage数据结构。因此管理成本很高。page数据结构的主要成员如下:/* * Each physical page in the...原创 2021-07-20 22:01:41 · 1782 阅读 · 1 评论 -
14.6 shrink_inactive_list函数
内存管理大多是以页为中心展开的,structpage数据结构显得非常重要。问题: structpage数据结构中的_count和_mapcount有什么区别? 答:_count表示page被引用的次数,_mapcount表示page被进程映射的次数 匿名页面和pagecache页面有什么区别? 答:pagecache也叫页缓冲或文件缓冲,它用于缓存文件的逻辑内容,从而加快对磁盘上数据的访问。而匿名页面是由malloc或mmap函数分配,没有和文件关联的。 struct...原创 2021-07-20 21:58:49 · 641 阅读 · 0 评论 -
14.5 shrink_active_list函数
缺页中断发送后,根据pte页表项的PRESENT位、pte内容是否为空(pte_none()宏)以及是否为文件等条件,相应的处理函数如下:1、匿名页面缺页中断do_anonymous_page()(1)判断条件: pte页表项中PRESENT没有置位、pte内容为空且没有指定vma->vm_ops->fault()函数指针。(2)应用场合: malloc()分配内存。2、文件映射缺页中断do_fault()(1)判断条件:pte页面表项中的PRESENT没有置位、p...原创 2021-07-20 21:58:23 · 574 阅读 · 0 评论 -
14.3 balance_pgdat函数
balance_pgdat()函数是回收页面的主函数。这个函数比较长,首先看一个框架,主体函数是一个很长的while循环。代码如下:/* * For kswapd, balance_pgdat() will work across all this node's zones until * they are all at high_wmark_pages(zone). * * Returns the final order kswapd was reclaiming at * ...原创 2021-07-19 09:19:29 · 942 阅读 · 1 评论 -
14.2 kswapd内核线程
linux内核中有一个非常重要的内核线程kswapd,负责在内存不足的情况下回收页面。kswapd内核线程被初始化为系统中每个NUMA内存节点创建一个名为"kswapd%d"的内核线程。static int __init kswapd_init(void){ int nid; swap_setup(); for_each_node_state(nid, N_MEMORY) kswapd_run(nid); hotcpu_notifier(cp...原创 2021-07-19 09:19:10 · 655 阅读 · 2 评论 -
14.1 LRU链表
在最近几十年操作系统的发展过程中,有很多页面交换算法,其中每个算法都有各自的优点和缺点。linux内核中采用的页面交换算法主要是LRU算法和第二次机会法(second chance)。 LRU链表 LRU是leastrecentlyused(最近最少使用)的缩写,LRU假定最近不使用的页在较短的时间内也不会频繁使用。在内存不足时,这些页面将成为被换出的候选者。内核使用双向链表来定义LRU链表,并且根据页面的类型分为LRU_ANON和LRU_FILE。每种类型根据页面的活跃分为活跃L...原创 2021-07-19 09:18:53 · 1127 阅读 · 2 评论 -
14. 回收页面
思考题: kswapd内核线程何时会被唤醒? 答:在伙伴系统分配内存时,发现zone的水位低于WMARK_LOW的时候,kswapd内核线程将被唤醒。 LRU链表如何知道page的活跃频繁度? 答:LRU按照先进先出的逻辑,页面首先进入LRU链表头,然后慢慢移动到链表尾,这有一个老化过程。另外,page有PG_referenced/PG_active标志位和页表的PTE_YOUNG位来实现第二次机会法。 kswapd按照什么原则来换出页面? 答:页面在活跃LRU链表,需要从链.原创 2021-07-19 09:18:32 · 153 阅读 · 0 评论 -
13.4 RMAP小结
早期的linux2.6的rmap实现如下图:父进程的VMA中有一个struct anon_vma数据结构(简称AVp),page->mapping指向AVp数据结构,另外父进程和子进程所有映射了页面的VMA时,只需要从物理页面的page->mapping找到AVp,再遍历AVp链表即可。当子进程的虚拟内存发生写时复制COW时,新分配的页面COW_Page->mapping依然指向父进程的AVp数据结构。这个模型非常简单,而且通俗易懂,但也有致命弱点。特别是在负载重的服务器中,例如父原创 2021-07-19 09:18:21 · 451 阅读 · 1 评论 -
13.3 子进程发生COW和RMAP应用
子进程发生COW 如果子进程的VMA发送COW那么会使用子进程VMA创建的anon_vma数据结构,即page->mapping指针指向子进程VMA对应的anon_vma数据结构。在do_wp_page()函数中处理COW场景的情况。子进程和父进程共享的匿名页面,子进程的VMA发送COW->缺页中断 ->handle_pte_fault ->do_wp_page ->分配一个新的匿名页面 ...原创 2021-07-19 09:18:10 · 275 阅读 · 0 评论 -
13.2 父进程创建子进程
父进程通过fork系统调用创建子进程时,子进程会复制父进程的进程地址空间VMA数据结构的内容作为自己的进程地址空间,并且会复制父进程的pte页面项内容到子进程的页表中,实现父子进程共享页表。多个不同子进程中的虚拟页面会同时映射到同一个物理页面,另外多个不相干的进程的虚拟页面也可以通过KSM机制映射到同一个物理页面中,这里暂时只讨论前者。为了实现RMAP反向映射系统,在子进程复制父进程的VMA时,需要添加hook钩子。 fork系统调用实现在kernel/fork.c文件中,在dup_mma...原创 2021-07-19 09:17:48 · 1664 阅读 · 0 评论 -
13.1 父进程分配匿名页面
父进程为自己的进程地址空间VMA分配物理内存时,通常会产生匿名页面。例如do_anonymous_page()会分配匿名页面,do_wp_page()发生写时复制COW时会生成一个新的匿名页面。以do_anonymous_page()分配一个新的匿名页面为例:[用户态malloc()分配内存->写入该内存->内核缺页中断->do_anonymous_page()]static int do_anonymous_page(struct mm_struct *mm, stru...原创 2021-07-19 09:17:33 · 414 阅读 · 0 评论 -
13. 反向映射RMAP
问题: 在linux 2.6.x内核中,如何从一个page找到所有映射该页面的VMA?反向映射可以带来哪些便利? 答:在linux2.6.x内核中,page->mapping指向的是anon_vma,当fork的时候,创建子进程后,当子进程发生了COW时,子进程的page->mapping也是指向了父进程的anon_vma(这句话特别重要),所以在一个page要找到所有映射该页面的VMA时,必须遍历父进程和子进程的所有VMA。在现在的新反向映射机制中,子进程发生了COW后,子进程的p.原创 2021-07-19 09:17:16 · 208 阅读 · 0 评论 -
12.3 页面锁PG_Locked
structpage数据结构成员flags定义了一个标志位PG_locked,内核利用PG_locked来设置一个页面锁。lock_page()函数用于申请页面锁,如果页面锁被其他进程占用了,那么会睡眠等待。[include/linux/pagemap.h]/* * lock_page may only be called if we have the page's inode pinned. */static inline void lock_page(struct page *page).原创 2021-07-19 09:16:41 · 877 阅读 · 0 评论 -
12.2 _count和_mapcount的区别
_count和_mapcount是structpage数据结构中非常重要的两个引用计数,且都是atomic_t类型的变量,其中,_count表示内核中引用该页面的次数。当_count的值为0时,表示该page页面为空闲或即将要被释放的页面。当_count的值大于0时,表示该page页面已经被分配且内核正在使用,暂时不会被释放。_count 内核中常用的加减_count引用计数的API为get_page()和put_page()。[include/linux/mm.h]static ...原创 2021-07-18 16:17:09 · 1625 阅读 · 0 评论 -
12.1 struct page数据结构
linux内核内存管理的实现以structpage为核心,类似城市的地标(如上海的东方明珠),其他所有的内存管理设施都为之展开,例如VMA管理、缺页中断、反向映射、页面分配与回收等。structpage数据结构定义在include/linux/mm_types.h头文件中,大量使用了C语言的联合体union来优化其数据结构的大小,因为每个物理页面都需要一个structpage数据结构。因此管理成本很高。page数据结构的主要成员如下:* * Each physical page in the ...原创 2021-07-18 16:16:54 · 597 阅读 · 1 评论 -
12. page引用计数
内存管理大多是以页为中心展开的,structpage数据结构显得非常重要。问题: structpage数据结构中的_count和_mapcount有什么区别? 答:_count表示page被引用的次数,_mapcount表示page被进程映射的次数 匿名页面和pagecache页面有什么区别? 答:pagecache也叫页缓冲或文件缓冲,它用于缓存文件的逻辑内容,从而加快对磁盘上数据的访问。而匿名页面是由malloc或mmap函数分配,没有和文件关联的。 struct...原创 2021-07-18 16:16:36 · 294 阅读 · 0 评论 -
11.5 缺页中断处理小结
缺页中断发送后,根据pte页表项的PRESENT位、pte内容是否为空(pte_none()宏)以及是否为文件等条件,相应的处理函数如下:1、匿名页面缺页中断do_anonymous_page()(1)判断条件: pte页表项中PRESENT没有置位、pte内容为空且没有指定vma->vm_ops->fault()函数指针。(2)应用场合: malloc()分配内存。2、文件映射缺页中断do_fault()(1)判断条件:pte页面表项中的PRESENT没有置位、p...原创 2021-07-18 16:16:09 · 524 阅读 · 0 评论 -
11.4 写时复制
do_wp_page()函数处理那些用户试图修改pte页表没有可写属性的页面,它新分配一个页面并且复制旧页面内容到新的页面中。/* * This routine handles present pages, when users try to write * to a shared page. It is done by copying the page to a new address * and decrementing the shared-page counter for the old原创 2021-07-18 16:15:42 · 380 阅读 · 1 评论 -
11.3 文件映射缺页中断
下面来看页面不在内存中且页表内容为空(!pte_present(entry)&&pte_none(entry))的另一种情况。即VMA定义了fault方式函数vma->vm_ops->fault。[handle_pte_fault()->do_fault()]/* * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurrent faults). *原创 2021-07-18 16:15:27 · 865 阅读 · 1 评论 -
11.2 匿名页面缺页中断
在缺页中断处理中,匿名页面处理的核心函数是do_anonymous_page(),代码实现在mm/memory.c文件中。在linux内核中没有关联到文件映射的页面称为匿名页面(Anonmous Page,简称anon page)。[handle_pte_fault()->do_anonymous_page()]/* * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurre原创 2021-07-18 16:15:07 · 552 阅读 · 1 评论 -
11.1 do_page_fault()缺页中断核心函数
缺页中断处理的核心函数是do_page_fault(),该函数的实现和具体的体系结构相关。[arch/arm/mm/fault.c]static int __kprobesdo_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs){ struct task_struct *tsk; struct mm_struct *mm; int fault, sig, code; uns原创 2021-07-18 16:14:43 · 4174 阅读 · 1 评论 -
11. 缺页中断处理概述
在之前介绍malloc()和mmap()两个用户API函数的内核实现时,我们发现它们只建立了进程地址空间,在用户空间可以看到虚拟内存,但没有建立虚拟内存和物理内存之间的映射关系。当进程访问这些还没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常(也称为"缺页中断"),linux内核必须处理此异常。缺页异常是内存管理当中最复杂和重要的一部分,需要考虑很多的细节,包括匿名页面、KSM页面、pagecache页面、写时复制、私有映射和共享映射等。 缺页异常处理依赖于处理器的体系结构,因此缺页异常...原创 2021-07-18 16:12:38 · 1509 阅读 · 1 评论 -
10. mmap
思考题: 请简述私有映射和共享映射的区别 答: 为什么第二次调用mmap时,linux内核没有捕捉到地址重叠并返回失败? 答:mmap概述: mmap/munmap接口是用户空间最常用的一个系统调用接口,无论是在用户进程中分配内存、读写大文件、链接动态库文件,还是多进程共享内存,都可以看到mmap/munmap的身影。mmap/munmap函数声明如下:#include <sys/mman.h>void *mmap(void *addr...原创 2021-07-18 16:13:59 · 295 阅读 · 0 评论