内存子系统
文章平均质量分 85
OS技术解密
阿里巴巴
展开
-
Linux memcg lru lock提升锁性能
继续检查,这个页是否在swapcache中,如果在,返回这个页地址加虚拟地址地址在页中的偏移,如果不在,获得一个内存页, 到swap设备上读取内容填到这个页,此处产生IO, 为Major page fault. 接下了就上把这个页加到swapcache,加入 LRU, 加入page table, 关联到所属的memcg, 并且添加反向映射,然后用户就可以正常使用了。解决的根本是改变页加入lru list和memcg的次序:如下所示,先关联memcg, 然后在加入lru list.get lru_lock;原创 2024-09-16 22:35:44 · 1327 阅读 · 0 评论 -
Linux per memcg lru lock
原来, 内核在引入 per memcg lru lists 后,并没有使用 per memcg lru lock, 还在使用旧的全局 lru lock 来管理全部 memcg lru lists。其实这些补丁和 Hugh Dickins 的补丁毫无关联, 并且在和 Johannes 的持续讨论中,解决方案的核心:page->memcg 的线性化已经进化了几个版本了, 从 relock 到 lock_page_memcg,再到 TestClearPageLRU,和 Google 的补丁是路线上的不同。原创 2024-09-16 22:29:33 · 978 阅读 · 0 评论 -
Linux匿名映射
在切入逆向映射的历史之前,我们还是简单看看一些基础的概念,这主要包括两个方面:一个是逆向映射的定义,另外一个是引入逆向映射的原因。1、什么是逆向映射(reverse mapping)?在聊逆向映射之前,我们先聊聊正向映射好了,当你明白了正向映射,逆向映射的概念也就易如反掌了。所谓正向映射,就是在已知虚拟地址和物理地址(或者page number、page struct)的情况下,为地址映射建立起完整的页表的过程。例如,进程分配了一段VMA之后,并无对应的page frame(即没有分配物理地址),直转载 2024-09-15 22:06:19 · 275 阅读 · 0 评论 -
终于讲清楚了,Linux Cgroup机制以及其树形结构怎么创建的
了解Linux Cgroup机制的都清楚,cgroup机制最终是通过树形结构表示的,既然是树形结构,我们必须搞清楚这个树形结构是怎么创建起来的,以及在内核源码中是怎么表达这种树形结构的,我们是否非常清楚怎么遍历整个树,本文将基于Linux5.15源码分析cgroup树形结构的创建过程。假设我们有如下层级结构:app就是test1和test2的父节点,test1和test2是兄弟节点,我们按照这个例子具体展开分析。原创 2024-09-15 14:19:56 · 785 阅读 · 0 评论 -
Linux block_device gendisk和hd_struct到底是个啥关系
根据块设备号dev,从blockdev_superblock拿到inode节点,为什么这里能拿到块设备文件(/dev/block/zram0)的inode,就是因为bdev_add时候将inode对象加入到blockdev_superblock的inode hash表中了,这里就能拿到。blkdev_get_by_dev函数返回了一个block_device,这个block_device跟前面zram块驱动blk_alloc_disk 生成的block_device有啥关系?原创 2024-09-07 00:18:35 · 807 阅读 · 0 评论 -
2024年Linux内核社区关于large folio和mthp的关键进展
所以唯一可行方案是THP recovery,也就是在被split的1GBTHP基础上,保留未被重新分配的页,并将已被重新分配的页的数据复制到额外的4KB页,然后将原有的1GB物理区域“物归原主”成THP。由于 mTHP 的 size 大于 4KiB 的 small folios,理论上,它更容易出现 false sharing 的情况,频繁迁移会导致内存跨 NUMA Node 来回 ping-pong,因此,在算法上,mTHP 暂时借用了 PMD-mapped 的 2-stage filter 机制。原创 2024-09-01 10:23:45 · 1207 阅读 · 0 评论 -
Linux TLB和cache
Linux TLB和cache。原创 2024-08-31 21:01:49 · 1100 阅读 · 0 评论 -
linux每个memory cgroup的lru链表是什么创建的 - 5.15内核
对Linux memory子系统有基本了解的都知道,linux内核通过LRU管理物理内存,不知道是否有思考过如下问题:LRU是全局一套,还是说每个memory cgroup拥有单独的一套LRU链表?直接揭晓答案:每个memory cgroup都会单独的LRU链表。原创 2024-08-29 19:46:30 · 685 阅读 · 0 评论 -
linux swap slot机制
其基本的思想是:swap slot cache从swap area中批量申请一些slots,之后内核在swap out操作申请slot时,直接从swap slot cache中获取,内核进行swap in释放slot时,也直接归还到swap slot cache中,这样比每次都向swap area逐个申请和释放要更加快速。判断的具体门限是以"SWAP_SLOTS_CACHE_SIZE"大小的倍数计,低于2倍时(相当于low watermark)就关闭swap slot cache。原创 2024-08-23 09:24:27 · 341 阅读 · 0 评论 -
zram机制 - zram_bvec_write为什么要调用zram_free_page
或者swap_writepage找一个空闲的slot,但是之前这个slot调用zram_slot_free_notify时,由于zram_slot_trylock失败,也没有在zram_slot_free_notify中调用zram_free_page,所以在本次写zram时,释放。有条件释放swapcache,看下面代码, 条件之一是mem_cgroup_swap_full(),也就是判定swap是否已经使用了50%,如果超过了50%,就要调用folio_free_swap进一步释放;原创 2024-08-22 23:22:06 · 377 阅读 · 0 评论 -
linux memory cgroup的memory.move_charge_at_immigrate含义
最开始某个进程是在cgroup A中,后面要迁移到cgroup B中,那么进程的内存计数是否要完全迁入B中,就是通过memory.move_charge_at_immigrate控制,如果目标cgroup也就是B设置了1到该字段中,那么进程的内存记账也要从cgroup A中去掉(uncharge from A),同时计算到B中(charge to B)。原创 2024-08-20 22:34:19 · 288 阅读 · 0 评论 -
源码视角看memory cgroup目录下创建目录以及读写节点发生了什么
【代码】源码视角看memory cgoup目录下创建目录以及读写节点发生了什么。原创 2024-08-17 09:52:39 · 108 阅读 · 0 评论 -
linux cgroup设计与实现机制
cgroup的全称为,中文翻译为控制组。内存CPUI/O和网络等。如下图所示,使用cgroup来限制进程组对内存的使用:在上图中,我们创建了 2 个cgroup(每个 cgroup 有 4 个进程),并且限制它们各自最多只能使用 2GB 的内存。如果使用超过 2GB 的内存,那么将会触发错误。cgroup通过把进程划分成控制组(一个控制组包含一个或多个进程),并且可以对控制组进行资源使用的控制,也就是说cgroup作用对象是控制组。cgroup提供了将进程组织成控制组的能力,然后通过使用。转载 2024-08-16 23:44:57 · 61 阅读 · 0 评论 -
Linux Swap机制关键点分析
参考文章:Linux Swap 从 userspace 到 kernel详解_kernel swap-CSDN博客Linux Swap 与 Zram 详解 - 泰晓科技一文聊透 Linux 缺页异常的处理—— 图解 Page Faults(下) - 简书原创 2024-06-30 18:17:58 · 431 阅读 · 0 评论 -
zram压缩机制看swapon系统调用
上面代码read_mapping_page是能够读取内容的关键是mapping对象,因为mapping->aops有readpage函数,但是这里mapping和mapping->aops是什么时候设置的?上面命令调用了linux的swapon系统调用启动zram0交换分区;mkswap命令向块设备文件/dev/block/zram0写入了swap_header信息。那么swapon_all命令执行了哪里的代码呢?但是这是什么代码路径设置进去的呢?原创 2024-06-29 22:27:54 · 437 阅读 · 0 评论 -
multi-generation lru系列 - workingset的适配
Linux 内存workingset Refault Distance算法源码及源码解析-CSDN博wen一文中我们分析了workingset算法的实现原理,内核引入mglru之后workingset算法也要做相应的适配,因为mglru算法使用了PID控制反馈算法,这其中就要统计refaulted次数和eviction次数,这些数据的统计就在workingset.c中实现的,接下来我们以v6.1源码分析workingset对于mglru的适配更新。原创 2023-10-03 20:46:46 · 391 阅读 · 0 评论 -
Linux回收内存的时候遇到PageWriteback和PageDirty脏页怎么处理?
我们知道内存回收会遇到各种情况的page,比如正在回写的page(PageWriteback)和脏页(PageDirty)的page,内核会等待PageWriteback完成回写呢,还是说直接跳过正在回写的页面。这两种选择各有优劣,如果等待Writeback完成会影响内存分配性能;如果直接跳过呢可能影响内存回收的效率。PageDirty的page也面临类似的问题,所以我们来看下内核v4-14源码中是如何处理这两种情况的。原创 2023-10-03 09:39:30 · 501 阅读 · 0 评论 -
multi-generation lru系列 - 怎么决定回收anon还是file
Linux 回收内存到底怎么计算anon/file回收比例,只是swappiness这么简单?-CSDN博客。原创 2023-10-02 23:26:31 · 339 阅读 · 0 评论 -
Linux 回收内存到底怎么计算anon/file回收比例,只是swappiness这么简单?
Linux内核为了区分冷热内存,将page以链表的形式保存,主要分为5个链表,除去evictable,我们主要关注另外四个链表:active file/inactive file,active anon和inactive anon链表,可以看到这主要分为两类,file和anon page,内存紧张的时候,内核开始从inactive tail定量回收page,那么这里面就有个很重要的选择:inactive file和inactive anon lru链表的回收比例到底怎么确定?原创 2023-09-29 22:36:29 · 573 阅读 · 0 评论 -
LWN:多代LRU方案的未来!
当一个 page 被访问时,它们会从较老的一代 list 移动到较新的一代,当需要回收内存时,会先从最古老的一代来开始回收 page。每一代的 page 都会随着时间的推移而变得老化,当最老的一代中的 page 都被回收掉了的时候,就会创造出新的一代。自这项工作的第一次发布以来最大的变动是在 "tier" (层)的定义上,tier 这个词现在被用来细分各代 page,这反过来又可以帮助更好地决定哪些 page 需要回收(reclaim),特别是在那些需要使用大量 buffered I/O 的系统中。转载 2023-09-24 22:34:44 · 239 阅读 · 0 评论 -
Linux 内存workingset Refault Distance算法源码及源码解析
内核mm子系统中有一个workingset.c实现了refault distance算法,发现网络逻辑介绍该算法的文章主要是黏贴自奔跑吧内核一书中的内容,军比较雷同,讲述的角度比较难以理解,我第一看到的时候琢磨了2天才明白,本文希望从更容易理解的角度来分析何为refault distance算法,以及内核引入该算法的原因,这就要从内核回收page面临的挑战说起。本文源码:v5.9。原创 2023-09-24 22:26:11 · 841 阅读 · 0 评论 -
Linux关于memory cgroup的几个要点
进程的内存可以分很多类型,比如page cache,slab,anon memory等,到底是限制的哪些内存?如果进程A已经运行起来占用了一些内存,之后,再将A加入memory cgroup限制,原来占用的内存会统计入新的memory cgroup?memory cgroup有memory.soft_limit_in_bytes和memory.limit_in_bytes,假设进程使用内存超过这两个限制,内存回收时机和路径是怎么样的?原创 2023-09-17 17:59:53 · 1244 阅读 · 0 评论 -
Linux mmap读/写触发共享文件页生命周期
Linux的mm内存子系统的核心功能就要要管理各种类型的page,确保能高效分配和释放,让物理内存得以最大化使用。初识内存系统往往关注的是page的申请和管理流程,容易忽略page的释放回收流程,其实理解mm中的内存回收和释放也是最核心的机制。原创 2023-09-11 23:52:07 · 400 阅读 · 0 评论 -
linux的dirty page回写磁盘过程中是否允许并发写入更新page?
众所周知Linux内核write系统调用采用pagecache机制加速写入过程,避免write系统调用长时间block应用进程,用户态进程执行write调用的时候,内核只是将用户态buffer copy到内核的pagecache当中,write系统调用就返回了,完全不需要等待数据完全写入存储设备,因为存储设备是的写入可能是个耗时很长的过程。内核正在回写page到存储设备的过程中,是否允许应用层同时更新page内容?应用层更新page是否会被block?本文将从理论和内核源码两个方面彻底分析该问题。原创 2023-09-10 07:59:17 · 567 阅读 · 0 评论 -
Linux page migration源码分析
Linux 内核page migration设计文档_nginux的博客-CSDN博客前文介绍了page migration迁移的设计思路,且内核文档介绍得知,总计需要20个steps完成迁移过程,本文目标是以源码视角对应到这20个step上面,加深对于页面迁移的理解。内核源码版本:Linux-5.9。下面再贴一下内核描述的20个step:__unmap_and_move函数//page:需要迁移的page//newPage: 迁移的目标page。原创 2023-08-27 10:41:38 · 448 阅读 · 0 评论 -
Linux 内核page migration设计文档
page migration设计之初是在numa system的各个node之间迁移physical pages,意味着进程页面的虚拟地址不会变化,物理地址发生改变,migration的目的将page迁移到临近的cpu上降低内存访问延迟。原创 2023-08-26 20:44:10 · 503 阅读 · 0 评论 -
自旋锁 spin_lock、 spin_lock_irq 以及 spin_lock_irqsave 的区别
能够停留下来认真读这篇文章的人大部分都已经了解了什么是自旋锁,至少知道自旋锁就是不停的询问资源有没有准备好的一把锁,这个从概念上很容易理解,当然他的内在也是很容易实现。转载 2023-08-23 11:10:53 · 893 阅读 · 0 评论 -
Linux源码剖析struct page结构体flags成员
/跟page reclaim的二次机会法有关//page缓存内存和磁盘数据一致//代表是脏页PG_dirty,//page在lru链表中PG_lru,//page在active lru链表中PG_active,//IO错误PG_error,//page是对应的是slab内存PG_slab,PG_arch_1,//不能换出//正在回写//马上开始回收,回收前设置//匿名页和shmem page设置该条件//被mlock了#endifPG_young,PG_idle,原创 2023-08-13 23:26:21 · 406 阅读 · 0 评论 -
Linux源码剖析匿名共享内存shmem原理
进程间共享匿名内存有两种重要的方式,其一是mmap设置MAP_SHARED | PRIVATE创建的虚拟地址区域,这片区域fork执行之后,由父子进程共享。其二是主动调用shmget/shmat相关接口。此外android操作系统的ashmem匿名共享内存也是基于linux内核的shmem实现。本文我们将从源码角度剖析内核shmem的设计和实现原理。原创 2023-08-13 17:18:43 · 1588 阅读 · 1 评论 -
cache line提升程序性能
数据结构中频繁访问的成员可以单独占用一个cache line或者相关的成员在不同的cache line中错开,以提高访问效率。比如linux内核struct zone数据结构中zone->lock和zone->lru_lock两个频繁访问的锁,可以让他们在不同的cache line中,以提高获取锁的效率。如果Data结构体不对齐到cache line,那么dArray[0]和dArray[1]会在同一个cacheline上面,两个线程同时修改结构体成员变量,由于缓存一致性机制,会导致缓存失效。......原创 2022-08-27 21:49:58 · 1552 阅读 · 0 评论 -
彻底搞懂内存屏障(上)
由于store buffer的大小是有限,上面例子中如果cpu1无法快速处理read invalidate消息,那么cpu0中的store buffer马上就会满了,所以arm增加了invalidate queue存放收到invalidate消息,收到invalidate消息放入invalidate queue中,然后给对方(cpu0)发送一个respone响应,但是此时并不真正处理invalidate消息,正因如此,invalidate queue又引入新的复杂性。.........原创 2022-08-28 22:24:24 · 2597 阅读 · 2 评论 -
彻底搞懂内存屏障(下)
线程cosume中使用 memory_order_acquire内存屏障,保证了consumer线程后面的所有读写(包括非原子)操作不能重排序到acquire之前,并且consumer的load操作一旦完成,线程producer release之前的读写操作对producer线程可见。我们知道,acquire/release只保证load完成之后,release之前的内存操作在load之后是可见,但是并不保证一个线程中的store(release)操作,立马对其他线程的load(acquire)可见。原创 2022-09-04 18:10:40 · 3155 阅读 · 0 评论 -
Linux mmap系统调用视角看缺页中断
实际开发过程中经常使用或者看到mmap函数,具体细节可以man mmap查看相关细节。这个系统调用是个多面手,应用空间申请内存(比如glibc库申请大内存使用的是mmap),还是读写大文件,链接动态库,多进程间共享内存都可以看到mmap的身影,要想真正的理解这个系统一方面是从这几种使用场景的需求上理解mmap,更重要的必须基于内核源码,深入剖析其每个参数具体对应的内核实现。内存拷贝次数以mmap映射文件场景来讲,mmap读写文件与read/write的相比少一次内存拷贝。原创 2023-08-07 22:16:35 · 673 阅读 · 0 评论 -
Linux 源码剖析匿名页的生命周期
本文以Linux5.9源码讲述。原创 2023-08-05 20:02:49 · 750 阅读 · 0 评论 -
linux页框回收之shrink_node函数源码剖析
Linux内存回收入口_nginux的博客-CSDN博客》前文我们概略的描述了几种内存回收入口,我们知道几种回收入口最终都会调用进入shrink_node函数,本文将以Linux 5.9源码来描述shrink_node函数的源码实现。原创 2023-07-30 11:31:37 · 632 阅读 · 0 评论 -
Linux内存回收入口
内存回收主要是有kswapd异步回收和direct reclaim同步回收两种入口,其中逻辑非常复杂,本文主要只概要描述不同回收场景下内核设计的主要思想,源码细节不同版本有不少区别,具体的分析后续会有专门的文章分析。原创 2023-07-29 14:27:00 · 345 阅读 · 0 评论 -
搞懂sparsemem稀疏内存模型
随着大内存和内存热插拔技术发展,内核物理内存越来越不连续,内核管理这种非连续物理内存的元数据metadata也需要随之发展,避免内存浪费,内核的sparse mem稀疏内存模型就是解决该问题。数据结构mmzone.h//根据sec number计算属于哪个root,即mem_section二位数组第一维的index//2048//相当于是[2048][256]的二维数组,每个数组元素是struct mem_section//为了节省空间,这个字段包含很多信息,具体见下面源码的解释/*原创 2023-07-28 23:00:00 · 743 阅读 · 0 评论 -
page _refcount和_mapcount字段
linux page有两个非常重要的引用计数字段_refcount和_mapcount,都是atomic_t类型,其中,_refcount表示内核中应用该page的次数。当_refcount = 0时,表示该page为空闲或者将要被释放。当_refcount > 0,表示该page页面已经被分配且内核正在使用,暂时不会被释放。原创 2023-07-24 22:59:08 · 944 阅读 · 0 评论