自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(73)
  • 收藏
  • 关注

原创 kfree_rcu实现浅析

原因在于,rcu callback链表里面,连着的都是struct rcu_head的对象,但是kfree释放的对象的地址,无法直接等同于这个struct rcu_head的对象的地址;奇怪的是,__kfree_rcu的第二个参数,获取的是offsetof(typeof(*(ptr)), rcu_head),最后将这个值,作为rcu_callback_t类型的变量,传递给了__call_rcu。注释写的非常清楚,kfree_rcu的作用,就是在一个gp后,将相关对象通过kfree释放掉。

2024-07-06 15:00:39 361

原创 rcu如何调用callback

如果对于系统启动之后第一次调用call_rcu的情况,callback链表显然是空的,则会走后续的逻辑,通过rcu_gp_in_progress判断是否处于宽限期中,且通过rcu_segcblist_restempty查看callback链表上的RCU_NEXT_READY_TAIL节点是否有callback在等待被调用。其中,初始化时,rcu_segcblist里的gp_seq会被初始化为0,而rsp->gp_seq会被初始化为一个很大的接近0xffffffff的数。下面分析call_rcu函数。

2024-07-06 12:07:28 684

原创 refault distance算法的一点理解

换成大白话来说就是,如果这个时候(第二次读入pagecache缓存),我把这个pagecache页放入活跃lru链表,有没有可能(或者说增大可能),在下次用户需要读取这个pagecache的时候,他还在lru链表上(无论是活跃还是非活跃链表),这样的话,就代表这个页还没被踢出lru链表,从而用户访问的时候,就没必要从存储介质中重新读了,毕竟从存储介质读内容的性能肯定比不上从内存里读,如果能直接从内存里(lru链表上)读到,岂不美哉?这个算法看了好几次了,都没太理解,今天记录一下,加深一下印象。

2024-06-07 20:01:06 356

原创 srcu浅析

为什么这么说呢,因为调用了srcu_flip之后,srcu_read_lock返回的index,就和调用srcu_flip前不一样了,也就意味着,后续的srcu_read_lock,增加的atomic变量,和原先的srcu_read_lock增加的atomic变量,不再是一个变量了,这就能保证宽限期N的同步工作。可以看到,srcu_read_lock函数是有返回值的,且该返回值需要传递给srcu_read_unlock函数,这是srcu的特别之处,内核需要知道当前代码是准备进入哪个srcu的临界区。

2024-06-02 17:56:58 858

原创 rcu nocb特性浅析

博客http://t.csdnimg.cn/EKdgI介绍了rcu的基本原理,但是在实际应用中,rcu的nocb特性也经常被使用,那nocb是个什么东西呢?本文代码基于linux内核4.19.195。

2024-05-18 09:42:24 732

原创 linux rcu浅析

rcu浅析

2024-02-23 19:44:42 1045 1

原创 resv_hugepages是什么

但我们mmap hugetlbfs的文件时,会传入一个size,代表我们想mmap的内存大小,hugetlbfs在我们mmap的时候,会进行大页内存剩余量的判断,如果剩余的物理大页不够的话是会拒绝mmap的,而如果剩余的物理大页足够的话,则会顺利完成mmap,并且会把mmap传入的size加到resv_hugepages中,表示有这么多的物理大页已经被预定了的意思。那么这个值什么时候会被减去呢?

2023-03-18 07:54:56 168

原创 记一次free memory比available memory大的问题排查

而available的值,是通过free的值,减去totalreserve_pages,加上pagecache后减去pagecache/2和wmark_low中的小者,再加上可回收的slab以及一点dentry中的内存。因而,从理论上分析,在pagecache比较少的机器中,确实是可能存在free memory比available memory大的,其根因是因为内存分配一般是不允许低于在low水线以下进行分配的,从而available的计算会根据low水线值做出调整。

2023-03-18 07:45:20 917

原创 hugetlbfs内存释放

结合先前的分析,private映射的页会在这个流程中就被释放掉了,而shared映射的页,由于加入radix tree时将引用计数又加了一,故这个流程里面不会被释放,而是在删除hugetlbfs文件的时候,从radix tree里面删除的时候才把相关内存页释放。从函数中我们可以看到,hugetlbfs对于共享映射以及private映射的实现是有区分的,共享映射时,会把相关的内存页加入到radix tree里面,而private映射则不会加入到radix tree里。

2023-02-05 17:12:59 267

原创 对x86上下文切换的一点理解

根本原因就在这里,因为__switch_to_asm是一个被C语言调用的函数,作为调用者,有义务保存相关寄存器,至于保存哪些寄存器,是由x86的函数调用约定规定的,因而,作为被调用方,只需要保存相关的没有被调用方保存的寄存器即可,剩下的寄存器在函数结束后由调用方自行恢复,这里如果还做保存就是浪费力气了。完成寄存器及内核栈的切换。第一次看这个函数,感觉就是标准的上下文切换写法,最开始把prev进程的rbp、rbx、r12、r13、r14、r15寄存器完成保存,最后面再恢复next进程的这些寄存器。

2023-01-21 22:46:44 294

原创 linux内核printk的一些并发处理

我们知道,linux内核为了支持在各种位置都能使用printk,做了不少的工作,这篇文章简单介绍一下printk的一些并发处理。本文基于linux内核4.19.195.printk最终会调用到vprintk_func函数。可以看到,这个函数有三个分支:vprintk_nmi、vprintk_safe、vprintk_default。其中,vprintk_default是正常走的分支,vprintk_nmi是在nmi中断中调用printk走的分支,vprintk_safe是在不安全的上下文中调用prin

2022-12-03 12:18:15 1030

原创 谈谈我对volatile的理解

volatile关键字

2022-11-20 21:33:24 137

原创 ksm页面合并的并发处理

ksm页面合并的并发处理

2022-11-11 20:53:12 394

原创 对linux内核protection_map的一点理解

在mmap流程中,我们最终会走到函数mmap_region()里面完成mmap的动作,mmap_region()函数会调用vm_get_page_prot函数,将用户态传入的flag转换成权限位存放在了vma->vm_page_prot里面。还有一个重要的点,通过查看Pxxx的定义,我们可以发现所有Px1x的值,都是不带有_PAGE_RW权限的,所以所有作为私有映射的页,在发生写操作时,就会陷入缺页中断完成处理了。本文代码基于linux内核4.19.195.下面重点分析这个权限值是怎么生成的。...

2022-07-27 19:46:56 420

原创 page owner特性浅析

linux内核的page owner特性,参考文档,主要是用来Tracking about who allocated each page,方便定位内存泄漏、内存占用问题。

2022-07-02 21:55:41 1795

原创 hugetlbfs的写时复制

本文分析基于linux内核4.19.195最近想到了一个以前没有考虑过的问题:hugetlbfs大页遇到cow时,是怎么处理的?最开始的想法是,按照cow的原理,内核会重新申请一个大页,供父进程或子进程中第一个触发写操作的进程进行使用,但事实真的是如此吗?这么做的话,如果我们一开始往/sys/kernel/mm/hugepages/hugepages-xxxkB/nr_hugepages里写的值不够会怎么样?...

2022-06-26 18:06:18 168

原创 /proc/vmstat输出含义

/proc/vmstat输出含义

2022-06-11 17:27:30 3177 1

原创 ZONE_MOVABLE的理解

https://blog.csdn.net/rikeyone/article/details/86498298

2022-05-15 15:16:07 184

转载 linux上构建GFP_ZONE_TABLE

https://blog.csdn.net/qqqqqq999999/article/details/90045500

2022-05-09 17:10:47 162

原创 slub内存分配/释放流程浅析

本文代码基于linux内核4.19.195在之前的文章中,笔者碰到了一个疑似slab内存泄漏的问题,故好好研究了一下slub内存的分配和释放机制,着重在于检查什么时候会从buddy中申请内存,什么时候会把slub内存释放给buddy,进而总结了一下,如下图...

2022-04-27 22:54:56 842

原创 slab的并发处理浅析

本文代码基于linux 4.19.195。最近看了不少slab(slub)相关的代码,觉得slub的并发处理做的很优雅,特此记录一下。先来看一个5.15内核的函数。static inline int heart_alloc_int(void){ int bit;again: bit = find_first_zero_bit(heart_irq_map, HEART_NUM_IRQS); if (bit >= HEART_NUM_IRQS) return -ENOSPC; i

2022-04-27 19:56:35 501

原创 一个疑似percpu内存泄漏问题排查

本文代码基于linux 4.19.195继之前出现了业务运行一段时间后,从meminfo中看到slab占用的内存增加的问题后,最近同事又发现了业务运行一段时间,percpu这一项占用的内存增多的问题。根据同事提供的数据,未运行业务时,percpu占用140M内存,运行一段时间业务然后终止业务,从meminfo中看到percpu占用了460M的内存。percpu原理可以参考文献。因为是系统启动后运行一段时间业务,导致的percpu内存占用增加,我们重点关注动态percpu变量的申请和释放的过程。动态

2022-04-15 21:14:38 1448

原创 一个疑似slab泄漏问题排查

本文代码基于linux内核4.19.195.这周同事反馈一个疑似slab内存泄漏的问题,问题是这样的。同事在做业务升级测试,不断的升级24小时后发现,通过/proc/meminfo看到的slab内存占用比不跑升级测试的机器多了3.5G(整个系统只有8G内存),怀疑是slab内存泄漏了。找他要了一台不跑升级的机器和一台跑升级测试的机器对比着看,有如下发现:通过free命令查看,available确实少了2.6G通过/proc/meminfo对比查看,确实是slab相关的几行有着较大的变化,其他条目

2022-04-09 17:59:02 2969

原创 drop_cache能drop掉hugetlbfs文件的pagecache吗?

本分分析基于linux内核4.19.195版本。我们知道,drop_cache有两个用途,第一个是清除掉page cache以释放出一些内存空间,第二个是调用shrinker的接口,这个接口会释放掉inode、dentry等文件系统相关的cache以及其他组件的一些东西。今天突然脑袋发热的问了自己一个问题:drop_cache能drop掉hugetlbfs文件的pagecache吗?按drop_cache的原理来说是没问题的,drop_cache会去遍历每个super_block下的所有inod

2022-03-22 22:07:54 714

原创 get_user_pages和get_user_pages_fast的区别

最近工作中经常遇见get_user_pages和get_user_pages_fast,虽然知道他们都是用来pin住一个页的,但是依然没搞明白后者是如何实现fast的,两者的区别具体在哪。刚好利用周末时间研究一下。本文的分析基于linux 4.19.195.先看看get_user_pages_fast函数的定义/** * get_user_pages_fast() - pin user pages in memory * @start: starting user address * @nr_pa

2022-03-20 22:42:53 3758

原创 从hugetlbfs看NUMA mempolicy是如何影响内存分配的

周末在家闲来无事,研究一下mempolicy对内存页分配的影响。分析基于linux内核4.19.195.先看看内核里面支持什么内存分配策略:enum { MPOL_DEFAULT, //默认使用进程的policy;如果进程也设置了MPOL_DEFAULT,则使用系统默认policy(在CPU本地节点分配内存) MPOL_PREFERRED, //在内存分配时优先指定的节点,失败时从附近的内存节点上分配内存 MPOL_BIND, //强制在指定的节点上分配内存,即只能在nodemask指定的内存节点

2022-03-20 12:21:20 447

原创 关于hugetlbfs如何均匀的在各个numa节点上预留内存的探索

本文分析基于linux内核4.19.195.在linux的实际使用中,使用hugetlbfs进行大页内存分配是一种常用的优化方法,而且我们知道,hugetlbfs能够根据需要,将不同numa节点上的内存分配给用户态程序。hugetlbfs常见的用法是,在内核启动完成后,通过写/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages接口预留适当数量的大页,然后通过hugetlbfs获得大页。那么,为了实现“将不同numa节点上的内存分配给用户态程序”,在写

2022-03-12 17:45:57 1043

原创 一个workqueue导致的性能问题

本文代码基于linux 4.19.195笔者最近遇到了一个workqueue导致性能问题,引发了笔者对workqueue机制的探索和思考。简单的抽象后,问题是这样的:一共有两个进程,假设称之为a进程和b进程。a进程在等待b进程完成一些工作,b进程在完成工作后会调用相关接口通知a进程。b进程完成工作的流程的最末尾的位置,有如下两个关键步骤:首先调用schedule_work_on触发一个work 1,b进程只需要触发即可,无需等待work 1完成;然后再调用work_on_cpu(本质上也是sch

2022-03-04 21:47:11 838

原创 percpu_ref状态迁移的并发思考

最近看了下percpu_ref的代码,感觉对于并发处理这块设计的挺巧妙的,写个博客记录一下。本文代码基于linux内核4.19.195.之前简单了解了一下percpu_ref的作用,当我们认为这个变量将不被使用的时候,我们会调用percpu_ref_kill试图终结这个变量的生命周期,这个函数最终会调用到__percpu_ref_switch_to_atomic。当吧percpu_ref变量转换成atomic类型之后,就可以按照atomic的方式来对该变量保护的变量进行相关解引用/释放的操作了。但是,转换

2022-01-21 21:33:41 657

原创 linux缺页中断的并发设计

缺页中断处理函数中,为了实现高效的并发操作,做了不少优化工作,使得锁的粒度非常小,并且很好的解决了多个线程对同一地址空间的并发处理问题。本文简单讲解一下我对缺页中断并发处理的几个小技巧的理解。本文继续linux内核4.19.195.首先,缺页中断能并发吗?缺页中断处理函数handle_mm_fault的注释中不是写着已经拿到了mm semaphore锁吗?怎么还会并发呢?/* * By the time we get here, we already hold the mm semaphore *

2022-01-07 21:06:41 1207 2

原创 逆向映射的使用场景

linux逆向映射使用场景

2022-01-03 17:36:50 250

原创 脏页跟踪流程

linux内核的脏页跟踪

2022-01-03 17:34:48 562

原创 大页与普通页在page结构体上的区别

当linux内核分配普通页或者大页时,都会对相应的page结构体做一定的初始化,初始化的内容因分配的页是大页或者普通页会有一定的区别,下面我们根据代码来看看这些区别。本文代码源于linux-4.19.195。直接由函数alloc_fresh_huge_page入手。/* * Common helper to allocate a fresh hugetlb page. All specific allocators * should use this function to get new huge

2021-12-17 20:54:40 415

原创 gfp_mask是0代表什么?

之前写的博客有一个遗留问题,find_get_page函数里指定了gfp_mask是0,这个0代表什么含义呢?内核的gfp.h文件里其实已经给出了答案:/* * GFP_ZONE_TABLE is a word size bitstring that is used for looking up the * zone to use given the lowest 4 bits of gfp_t. Entries are GFP_ZONES_SHIFT * bits long and there

2021-12-14 21:12:47 425

原创 linux页面迁移与用户态访问的并发处理

解决完上篇博客的问题后,随之而来的,又是一堆因好奇心引发的问题,其中,最让我好奇的是这个问题:内核的kcompactd线程在做页面迁移,刚好用户态的进程也在对该页面进行读写操作,这两个步骤是并行的,那么,内核是如何做好并发保护工作的?具体一点的说,就是内核如何保证,迁移前,用户态对该内存的读写是在迁移前的页,迁移后,用户态对该内存的读写是在迁移后的页,不会发生交叉的情况,也就是不会发生一部分写入的内容遗留在迁移前的页,而没有同步到迁移后的页。此问题可以扩展为一般类问题:内核线程对用户task的内存进行迁

2021-12-12 18:00:50 424

原创 谈谈对linux操作系统中断和异常的理解

先来个网上到处都有的定义吧:中断可分为同步(synchronous)中断和异步(asynchronous)中断:同步中断是当指令执行时由 CPU 控制单元主动产生,之所以称为同步,是因为只有在一条指令执行完毕后 CPU 才会发出中断,而不是发生在代码指令执行期间,比如系统调用,根据 Intel 官方资料,同步中断称为异常(exception),异常可分为故障(fault)、陷阱(trap)、终止(abort)三类。异步中断是指由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能够在指令之间发生

2021-11-28 18:22:51 1348

原创 为什么要引入Scheduling Domains?

在复杂的系统,调度器要解决的一个首要问题就是如何发挥这么多 CPU 的性能,使得负载均衡。不存某些 CPU 一直很忙,进程在排队等待运行,而某些 CPU 却是处于空闲状态。但是在这些 CPU 之间进行 Load Balance 是有代价的,比如对处于两个不同物理 CPU 的进程之间进行负载平衡的话,将会使得 Cache 失效。造成效率的下降。而且过多的 Load Balance 会大量占用 CPU 资源。scheduling domains的引入就是为了解决上述问题的...

2021-11-28 17:46:04 72

原创 kprobe_events接口寄存器名字

之所以想写这篇博客,是因为之前在使用ftrace的kprobe_events调试的时候,输入的寄存器名字一直不对,导致写kprobe_events接口一直报错。之前一直用的arm32,r0,r1这些用的就很方便,但是到了x86平台上,试了rdi,rsi等,一直都不对。索性,就去看看内核代码,确认究竟寄存器名字应该写什么。下面通过代码演示我的查找步骤,代码基于linux-4.19.195首先,找到内核注册kprobe_events接口的地方。static const struct file_operat

2021-10-30 11:24:10 352

原创 用户态中断在KAKAOS上的实现

之前linux内核社区提出来用户态中断的概念,详见 链接 ,主要功能如下:如果该进程正在用户空间中运行,那么 handler 函数将会被立即调用,并取得相应的 vector 编号。一旦 handler处理程序返回了,那么就会在之前被中断的位置继续执行。如果接收者此时被阻塞在内核的系统调用中,那么该中断将会在返回到用户空间时被触发,也就是说并不会打断当前正在进行的系统调用。嗯,按照我的理解来说,就是一个用户态进程运行的好好的,如果系统中其他进程或者内核认为这个用户态进程需要紧急响应某个事情,就向这个进

2021-10-24 12:24:15 235

原创 kcompactd浅析

之所以想写这篇文章,是因为一个问题:如果我使用slab的时候向内核申请了一个不可移动页,但是此时内核没有不可移动页了,只剩下unmovable的页,那么,根据伙伴系统的设计,会从movable页里面取出来一个用于分配(见__rmqueue_fallback函数),那么,根据内存规整子系统设计的原则,可移动页是最适合做规整的,如果这个slab使用的页面被规整程序移动了,那slab系统不就乱套了吗?此外,书中好像并没有看到说不可移动页是怎么做规整的,那么,规整子系统真的移动了不可移动页吗,如果为真,那这个页是

2021-10-22 21:36:42 2507

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除