linux
文章平均质量分 67
kaka__55
这个作者很懒,什么都没留下…
展开
-
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 · 662 阅读 · 0 评论 -
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 · 1208 阅读 · 2 评论 -
逆向映射的使用场景
linux逆向映射使用场景原创 2022-01-03 17:36:50 · 252 阅读 · 0 评论 -
脏页跟踪流程
linux内核的脏页跟踪原创 2022-01-03 17:34:48 · 572 阅读 · 0 评论 -
linux页面迁移与用户态访问的并发处理
解决完上篇博客的问题后,随之而来的,又是一堆因好奇心引发的问题,其中,最让我好奇的是这个问题:内核的kcompactd线程在做页面迁移,刚好用户态的进程也在对该页面进行读写操作,这两个步骤是并行的,那么,内核是如何做好并发保护工作的?具体一点的说,就是内核如何保证,迁移前,用户态对该内存的读写是在迁移前的页,迁移后,用户态对该内存的读写是在迁移后的页,不会发生交叉的情况,也就是不会发生一部分写入的内容遗留在迁移前的页,而没有同步到迁移后的页。此问题可以扩展为一般类问题:内核线程对用户task的内存进行迁原创 2021-12-12 18:00:50 · 426 阅读 · 0 评论 -
谈谈对linux操作系统中断和异常的理解
先来个网上到处都有的定义吧:中断可分为同步(synchronous)中断和异步(asynchronous)中断:同步中断是当指令执行时由 CPU 控制单元主动产生,之所以称为同步,是因为只有在一条指令执行完毕后 CPU 才会发出中断,而不是发生在代码指令执行期间,比如系统调用,根据 Intel 官方资料,同步中断称为异常(exception),异常可分为故障(fault)、陷阱(trap)、终止(abort)三类。异步中断是指由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能够在指令之间发生原创 2021-11-28 18:22:51 · 1355 阅读 · 0 评论 -
为什么要引入Scheduling Domains?
在复杂的系统,调度器要解决的一个首要问题就是如何发挥这么多 CPU 的性能,使得负载均衡。不存某些 CPU 一直很忙,进程在排队等待运行,而某些 CPU 却是处于空闲状态。但是在这些 CPU 之间进行 Load Balance 是有代价的,比如对处于两个不同物理 CPU 的进程之间进行负载平衡的话,将会使得 Cache 失效。造成效率的下降。而且过多的 Load Balance 会大量占用 CPU 资源。scheduling domains的引入就是为了解决上述问题的...原创 2021-11-28 17:46:04 · 73 阅读 · 0 评论 -
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 阅读 · 0 评论 -
用户态中断在KAKAOS上的实现
之前linux内核社区提出来用户态中断的概念,详见 链接 ,主要功能如下:如果该进程正在用户空间中运行,那么 handler 函数将会被立即调用,并取得相应的 vector 编号。一旦 handler处理程序返回了,那么就会在之前被中断的位置继续执行。如果接收者此时被阻塞在内核的系统调用中,那么该中断将会在返回到用户空间时被触发,也就是说并不会打断当前正在进行的系统调用。嗯,按照我的理解来说,就是一个用户态进程运行的好好的,如果系统中其他进程或者内核认为这个用户态进程需要紧急响应某个事情,就向这个进原创 2021-10-24 12:24:15 · 237 阅读 · 0 评论 -
kcompactd浅析
之所以想写这篇文章,是因为一个问题:如果我使用slab的时候向内核申请了一个不可移动页,但是此时内核没有不可移动页了,只剩下unmovable的页,那么,根据伙伴系统的设计,会从movable页里面取出来一个用于分配(见__rmqueue_fallback函数),那么,根据内存规整子系统设计的原则,可移动页是最适合做规整的,如果这个slab使用的页面被规整程序移动了,那slab系统不就乱套了吗?此外,书中好像并没有看到说不可移动页是怎么做规整的,那么,规整子系统真的移动了不可移动页吗,如果为真,那这个页是原创 2021-10-22 21:36:42 · 2537 阅读 · 0 评论 -
处理softirq的时候能响应硬件中断吗?
对这个问题一直很好奇,这里特指的完成硬件中断的处理后去处理软中断的时候,而不是ksoftirqd线程处理软中断的时候。我们知道,中断退出前会调用irq_exit函数,irq_exit函数一进来就把中断关了(我觉得是为了防止注册的中断处理函数把中断打开的情况),然后最后调用到了invoke_irq()处理软中断,那么调用invoke_irq()的时候,硬件中断是disable的void irq_exit(void){#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED loca原创 2021-09-25 11:24:53 · 165 阅读 · 0 评论 -
调度子系统的几个sysctl变量含义
sysctl_sched_latency 调度周期sysctl_sched_min_granularity 当一个task错过了唤醒抢占,确保它不会等待一个调度周期才能够被调度,目的是减少调度时延,具体可以看git show -p f685ceacabsysctl_sched_wakeup_granularity 具体作用可以查看wakeup_preempt_entity函数,用于防止唤醒抢占可能带来的频繁上下文切换sched_nr_latency 具体查看函数__sched_period,用于计算调原创 2021-09-25 10:50:17 · 168 阅读 · 0 评论 -
struct percpu_ref结构体浅析
在网上找了一圈都没看到什么struct percpu_ref的资料,索性自己研究一下。首先,参考这里的介绍,percpu_ref和kref变量类似,通常用做引用计数器,那么为什么还要做一个新的引用计数器呢?atomic_t有什么不足吗?原文是这么说的:If references are added and removed frequently over an object’s lifetime, though, that atomic_t variable can become a performan原创 2021-09-25 10:48:50 · 956 阅读 · 0 评论 -
percpu变量的并发操作
当工作中需要使用percpu变量,才知道自己对percpu变量的理解有多薄弱,所以趁现在把经验心得记录下来。percpu变量基础(wowotech):http://www.wowotech.net/kernel_synchronization/per-cpu.html一般来说,对于per-cpu的变量,我们一般需要通过关抢占进行并发保护操作;这其中就有几种方式:通过关中断local_irq_save来达到关抢占的效果(这样还能支持嵌套)通过this_cpu_***这类函数操作,见下图说明在hot原创 2021-09-24 21:46:19 · 784 阅读 · 0 评论 -
Linux内存回收之LRU链表和第二次机会法
一 LRU回收算法LRU算法,假定最近最少使用的页,在较短的时间内页不会使用,所以这些页成为回收的候选者.内存回收的核心是围绕LRU链表来进行操作,Linux内核实现了5种LRU链表类型不活跃匿名页表链表(LRU_INACTIVE_ANON)//shmem活跃匿名页表链表(LRU_ACTIVE_ANON)//不活跃文件映射页表链表(LRU_INACTIVE_FILE)活跃文件映射页表链表(LRU_ACTIVE_FILE)不可回收页表链表(LRU_UNEVICTA转载 2021-04-24 22:40:24 · 711 阅读 · 0 评论 -
谈谈自己对内存回收的理解
内存回收,是内核在内存不足的情况下,一种释放内存的方法,在4.4.198内核里,主要有两个函数涉及内存回收,一个是kswapd,一个是drop_cache;先说说kswapd,这是一个内核线程,每个内存节点都有一个这样的内核线程,名字是kswapd%d;在alloc_page函数中用低水位分配内存失败后,进入慢速路径的第一件事情static inline struct page *__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,原创 2021-04-24 11:42:03 · 616 阅读 · 0 评论 -
linux内存管理子系统里的各种算法设计的初衷是什么?
首先说一下写这篇博文的初衷:我对linux的学习,是不是都过度的专注于各个模块的实现,而忘记了其背后的设计初衷呢?以下观点纯属作者个人观点,如果有写的不对的地方请指出。**伙伴算法的初衷:**为了兼顾内存分配效率以及减少外部碎片而设计出来的一种分配算法。百度百科对伙伴算法的定义:计算机算法的一种,是为了核心内存管理能够快速响应请求,尽可能地在提高内存利用率的同时减少内存碎片的一种算法。**slab算法的初衷:**为了不同大小的对象而设计的一个分配算法,并兼顾效率以及碎片化程度。另外,SLUB分配器原创 2021-04-11 18:35:57 · 135 阅读 · 0 评论 -
linux内核page结构体的PG_referenced和PG_active标志
linux内核使用了lru算法来置换内存页面,但是实际上并不是纯的lru算法,里面掺杂了很多别的思想,比如第二次机会,比如双时钟指针等等。这里着重说一下第二次机会的体现。在内核中有一个mark_page_accessed函数,它实际上体现一个状态机,这是它的实现:if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) { activate_page(pa转载 2021-04-03 10:10:49 · 412 阅读 · 0 评论 -
低版本内核与高版本内核__zone_watermark_ok函数的变化
机缘巧合,最近研究了一下linux内核__zone_watermark_ok函数,发现高版本(4.4)和低版本3.14之前有所区别,特此记录一下。先上3.14版本的代码/* * Return true if free pages are above 'mark'. This takes into account the order * of the allocation. */static bool __zone_watermark_ok(struct zone *z, unsigned int原创 2020-11-22 16:58:37 · 438 阅读 · 2 评论 -
对linux内核DAX不支持arm的理解
前几天看内核代码,看到CONFIG_FS_DAX居然是depends on !(ARM || MIPS || SPARC),非常疑惑,于是简单的探究了一下:查看内核提交记录,是Commit d92576f1引入的,提交记录如下:该提交在Documentation/filesystems/dax.txt加了一句话:The DAX code does not work correctly on architectures which have virtually mapped caches such a原创 2020-11-01 16:26:48 · 478 阅读 · 0 评论 -
三个PTE标志位的含义:PTE_DIRTY,PTE_YOUNG,PTE_PRESENT
PTE_DIRTY:CPU在写操作时会设置该标志位,表示对应页面被写过,为脏页。PTE_YOUNG:CPU访问该页时会设置该标志位。在页面换出时,如果该标志位置位了,说明该页刚被访问过,页面是young的,不适合把该页换出,同时清除该标志位。PTE_PRESENT:表示页在内存中。...原创 2020-08-02 20:58:51 · 2237 阅读 · 0 评论 -
记录一个linux内核态打印时间方法
struct rtc_time tm;struct timeval time_now;(void)do_gettimeofday(&time_now);rtc_time_to_tm(time_now.tv_sec, &tm);pr_info("[%02d%02d%02d%02d%02d%02d]\n", tm.tm_year + 1900, tm.tm_mday, tm.tm_hour, tm.tm_hour, tm.tm_min, tm.tm_sec);原创 2020-07-26 22:39:39 · 690 阅读 · 0 评论 -
用strace跟踪一个正在运行的进程
记录一下这个技巧。用strace跟踪一个正在运行的进程,先用ps查看进程的pid,然后strace -p $pid原创 2020-07-26 22:34:09 · 1128 阅读 · 0 评论