Huo的藏经阁
linux爱好者,平时喜欢阅读内核源码,从源码角度解开操作系统神秘面纱
展开
-
linux那些事之SYSCALL_DEFINEx
内核代码中常常在查看系统调用宏时常常会看到使用SYSCALL_DEFINEX一系列宏定义来定义内核针对系统调用接口的定义该宏位于include\linux\syscalls.h文件中,针对系统调用的参数不同,使用了一系列的宏进行方便定义:针对不同的参数个数,一般会使用不同的宏定义,例如open系统调用总共由三个参数,内核中针对open的系统调用为:上述几个宏定义,最终都是调用SYSCALL_DEFINEx,在该宏中x参数代表的是系统调用参数个数,name为系统调用名称,例如open,被_#原创 2022-06-06 08:52:46 · 719 阅读 · 0 评论 -
linux用户态切换到内核态方法
经常游荡在内核源码中,反而对一些基础的东西,确实总结,总结以下经常遇到的问题,linux 用户如何从用户态切换到内核态几个方法:系统调用syscall系统调用是最为常见,也是用于经常使用能够直接感受到的方法。用户态进程通过系统调用申请使用操作系统提供的服务完成工资。例如经常见到的open, fork等函数都需要切换到内核进程,由内核进程完成之后再返回到用户层上去。用户可以通过系统调用内核中的调度,内存等资源,主要工作步骤:Step 1)The processes executed in.原创 2022-05-20 06:00:55 · 2169 阅读 · 0 评论 -
linux内核那些事之内存规整(memory compact)
内存规整是Mel Gormal开发防止内存碎片anti-fragmen pach补丁的第二个部分Avoiding fragmentation with page clustering v27 [LWN.net],主要用于解决当系统长时间运行之后,造成比较碎化内存时,通过内存规整将处于可以移动MOVE的类型内存,重新进行页迁移 整合出较大连续物理内存:内存规整机制原因比较简单:利用类似快慢指针技巧,当需要对一个zone进行内存规整时,使用migrate_pfn和free_pfn两个遍历; m原创 2022-05-09 20:05:04 · 1528 阅读 · 0 评论 -
linux那些事之shrink_node
shrink_node为实施内存回收的一个关键节点处理:不管是kswapd回收还是慢速申请直接回收都会通过shrink_node进行内存回收,shrink_nodeshrink_node主要是根据scan_control 控制内存回收力度,来决定具体回收的行为和策略,后续通过shrink_node_memcgs根据scan_control回收策略决定LRU和slab回收行为:static void shrink_node(pg_data_t *pgdat, struct scan_c原创 2022-05-01 11:11:41 · 1388 阅读 · 0 评论 -
linux那些事之kswapd
内核从buddy中申请内存时,首先会尝试通过快速内存申请通道get_page_free_freelist中申请内存,当快速内存申请失败需要进入慢速申请通道尝试各自内存回收和规整等手段,尝试整理出空闲内存。尝试进行内存回收的第一个手段就是启动kswapd线程,对LRU中和slab中的内存进行回收。kswapd线程属于内存线程,在系统启动启动是,内核就会创建kswapd<node-id>线程,为了防止对性能影响,每个node节点各自创建一个kswapd线程,以node id为后缀,原创 2022-04-22 08:43:24 · 1582 阅读 · 0 评论 -
linux那些事之numa balance
numa balancenuma balance是页迁移技术最重要也是最开始使用应用的技术,主要是为解决由于调度器进程在两个node迁移造成访问内存性能问题。numba balance通过页迁移技术,将不在运行节点的内存迁移到所运行的节点上。对应numa balance要注意几点:防止进程在两个节点之前来回切换造成频繁进行页迁移(ping pang现场)从而影响性能。numa balance本身就是为了提高性能,不能因为造成频繁页迁移而对性能进行一个反向优化。 多个线程分布在不同线程 访.原创 2022-04-15 19:31:08 · 3105 阅读 · 1 评论 -
linux那些事之页迁移(page migratiom)
Page migration页迁移技术是内核中内存管理的一种比较重要的技术,最早该技术诞生于NUMA系统中(Page migration [LWN.net]),后续由于内存规整以及CMA和COW技术的出现,也需要用到页迁移技术,逐渐称为内核内存子系统中占有比较重要地位。页迁移在NUMA系统中的应用NUMA系统中,每个cpu运行的进程申请内存时尽量从该cpu本地节点中内存中(local memory)速度,这样才能够获得最佳内存访问性能,但是由于内核进程调度系统,当进程数量过多时,调度系统会将进程原创 2022-04-10 18:40:53 · 2366 阅读 · 0 评论 -
linux那些事之contiguous memory allocator(CMA)
在linux驱动开发过程中经常需要使用到连续大块物理内存,尤其是DMA设备。而实际在系统经过长时间的允许之后,物理内存会出现比较严重的碎片化现象,虽然通过内存规整,内存回收等手动可以清理出一段连续的物理内存,但是并不能保证一定能够申请较大连续物理块。最初连续申请较大块物理内存,一般都是只在DMA场景中使用,因此内核专门把物理内存划分出ZONE_DMA专门用于DMA内存申请(当然划分DMA_ZONE还有其他原因,在较早DMA中由于DMA寻址地址限制 只能将一定范围的物理内存),用于解决DMA申请连续物理内存问原创 2022-04-05 21:46:08 · 2281 阅读 · 0 评论 -
linux那些事之copy on write(COW)
copy on write(COW)特性主要用于在forck时节省内存空间,可以防止在fork时将父进程中的所有数据全局复制一份出来。可以想象如果fork是将所有父进程中的数据全部复制一份给子进程会造成严重副作用:复制大量不必要的数据会造成占有大量物理内存 fork时造成大量数据会比较耗时操作性能严重损耗。当一个程序在复制之后调用exec,则会造成更严重性能浪费。意味着fork时复制的数据时完全没有用。内核在解决次问题时,fork并不会复制父进程整个地址空间,也是只复制其page table,则这样原创 2022-03-26 00:00:00 · 2154 阅读 · 0 评论 -
linux那些事之反向映射RMAP
内核中经常出现一个page 被多个虚拟进程使用,例如fork是子进程会继承父进程的页面,同样在开始时拥有相同的页面,此时一个page会对应多个进程VMA:在共享内存场景中,一个物理内存也会被多个进程同时使用。针对上述场景,如果是一个文件被多个进程使用,实际上只对应一个物理页,此时page为page cache,page结构中可以通过page中的struct address_space *mapping结构进行管理。而针对匿名页由于没有对应具体文件,但是又经常需要用到根据page查找到对应的所有正原创 2022-03-23 21:16:14 · 1304 阅读 · 0 评论 -
linux内核那些事之buddy(慢速申请内存__alloc_pages_slowpath)(5)
内核提供__alloc_pages_nodemask接口申请物理内存主要分为两个部分:快速申请物理内存get_page_from_freelist(inux内核那些事之buddy(快速分配get_page_from_freelist())(3))和慢速申请__alloc_pages_slowpath慢速申请内存部分两个部分如下图:首先尝试快速申请内存get_page_from_freelist,在快速内存中如果当前水位wmark_pages满足要求则调用get_page_from_free_are.原创 2022-03-22 09:14:39 · 1225 阅读 · 0 评论 -
linux那些事之LRU(4)
当物理内存实际比较紧张时,内存水位处于较低water level时,会触发间接回收内存kswapd或者直接回收内存,从inactive LRU list中将不常用的内存 置换到内存中。vmscan系统提供shrink_inactive_list接口,用于将inactive LRU list中的页面置换出去功能。...原创 2022-03-20 16:54:03 · 1668 阅读 · 0 评论 -
linux那些事之LRU(3)
继续承接《linux那些事之LRU(2)》, 。shrink_active_list()函数中需要将调用isolate_lru_pages函数将active LRU中从链表尾部隔离出nr_to_scan页物理页面出来,准备将其加入到inactive LRU中isolate_lru_pagesisolate_lru_pages()为从将指定的LRU中分离出nr_to_scan个页面,该函数会将该LRU中page referecent为非零的页面全部挑选出来,该函数定义为:unsigned lon原创 2022-03-17 16:49:20 · 1427 阅读 · 0 评论 -
linux那些事之LRU(2)
继续《linux那些事之LRU(1)》,以匿名页 分析page 在不同时期所处位置说明page LRU。系统上电memblock->buddy free list系统上电之后,在初始化造成阶段此时buddy 并没有初始化建立,早期early阶段内存是被memblock接管(请参考《linux内核那些事之early boot memory-memblock》和《linux内核那些事之buddy》),memblock函数通过调用memblock_free_pages 将物理内存 按照页形式加入到b原创 2022-03-13 17:38:09 · 2878 阅读 · 0 评论 -
linux那些事之LRU(1)
一个物理页被分配之后,page其所挂载的链表从buddy空闲链表中摘除,会进入到active 或者inactive链表中,当物理内存water mark存在压力时会根据LRU(least recently unsed)策略将很久没有使用的物理页内存swap或者写入到磁盘中,以便将该页空闲出来供其分配使用。在各种服务器中应用程序 为了提高性能,大都使用内存密集性策略,因此随着长时间使用或者较多服务时会出现内存压力,因此采用合理策略从正在使用的物理页中选出合适的物理内存swap到磁盘中,以供分配使用,显得特原创 2022-03-10 21:46:56 · 2830 阅读 · 0 评论 -
linux那些事之page cache
page cachepage cache又称高速缓存,主要是针对文件文件系统,为了减少不必要的磁盘IO操作(读/写)造成卡顿问题,内核将磁盘文件中的内容缓存到内存中,并选择适当时机对磁盘进行读写操作。page cache在linux文件系统中占用重要地位。主要是由于CPU访问磁盘比从内存中读取要慢上百甚至上千倍;同时利用空间和时间局部性,当系统访问该文件中一定位置的内容之后,那么经常会很快访问附近位置,如果能提前将文件一部分内容缓存到内存中将会加快对文件操作效率。he Linux kernel原创 2022-03-06 08:35:31 · 1938 阅读 · 2 评论 -
linux那些事之page fault(do_fault)(5)
do_fault为 文件page fault处理,当vma被具体映射到某个文件使,发生page fault将会被认为是文件page fault:static vm_fault_t handle_pte_fault(struct vm_fault *vmf){ ... ... if (!vmf->pte) { if (vma_is_anonymous(vmf->vma)) return do_anonymous_page(vmf); else r原创 2022-03-04 00:00:00 · 1409 阅读 · 3 评论 -
linux那些事之zero page
zero pagezero page是一个特殊的物理页,里面值全部为0,zero page是针对匿名页场景专门进行优化,主要是节省内存和对性能进行了一定优化。当malloc或者mapp一段虚拟内存后,第一次对该内存访问为读操作,将会发生匿名page fault。do_anonymous_page处理,由于第一次为读操作还未发生写操作,因此发生一个zero page,为其申请一个特殊物理页zero page。zero page 好处:zero page是一个全局唯一的一个物理页,且只有一个物理页。原创 2022-03-01 00:00:00 · 1137 阅读 · 0 评论 -
linux内核那些事之mempolicy(2)
mempolicy相关系统调用主要有set_mempolicy/get_mempolicy 、mbind主要配置task/process policy和vma policy,如下图:原创 2022-02-25 19:54:29 · 1744 阅读 · 0 评论 -
linux内核那些事之mempolicy(1)
mempolicy为内核分配内存策略管理模块,主要是在numa系统中用于根据指定的内存分配策略决定分配的内存所处的NUMA节点中:In the Linux kernel, “memory policy” determines from which node the kernel will allocate memory in a NUMA system or in an emulated NUMA system由于NUMA系统中有多个内存控制器,每个控制器并不是与每个cpu距离相等的,如下图所示原创 2022-02-24 00:00:00 · 1213 阅读 · 0 评论 -
linux内核那些事之zone(zone watermark)(3)
为了对每个zone区域的物理内存使用情况,以便更好解决内存紧张而做出不同策略,同时又不影响性能,内核将zone中物理内存按照不同的使用程度划分为不同水位(watermakr),以更好采取不同的策略。《understanding linux virtual memory》一书中对watermark有了很好的说明,虽然它是以2.4内核版本为基础,但是对于理解watermark还是比较重要,:在2.4版本中zone watermark定义为:typedef struct zone_struct {原创 2022-02-22 00:00:00 · 1205 阅读 · 0 评论 -
linux内核那些事之buddy(anti-fragment机制-steal page)(5)
继<linux内核那些事之buddy(anti-fragment机制)(4)>,在同一个zone内指定的migrate type中没有足够内存,会启动fallback机制,从fallbacks数组中寻找到合适其他type中获取到steal page,实施steal page核心处理函数为steal_suitable_fallback。steal_suitable_fallbacksteal_suitable_fallback定义如下:void steal_suitable_fall原创 2022-02-20 00:30:00 · 644 阅读 · 0 评论 -
linux内核那些事之buddy(anti-fragment机制)(4)
程序运行过程中,有些内存是短暂的驻留 用完一段时间之后就可以将内存释放以供后面再次使用,但是有些内存一旦申请之后,会长期使用而得不到释放。长久运行有可能造成碎片。以《professional linux kernel architecture》中用例说明如下图所示:以上图中有60个page,经过长期运行内存不断释放和申请,最终占用的内存分布到各个角落,还剩余大约25的pages分开分布空闲状态,针对这种场景由于空闲页周围都被占用,无法利用buddy算法的优势进行合并,因此尽管还有大约25%的空闲原创 2022-02-13 11:49:06 · 699 阅读 · 0 评论 -
linux内核那些事之buddy(快速分配get_page_from_freelist())(3)
《linux内核那些事之buddy(2)》buddy算法内存申__alloc_pages_nodemask()函数申请内存时首先调用get_page_from_freelist进行第一次尝试申请内存(可以称为快速申请,所谓快速申请相对慢速申请相对来说),如果第一次尝试申请内存失败则进入__alloc_pages_slowpath()慢速申请通道。get_page_from_freelist()get_page_from_freelist()为buddy算法第一次尝试申请内存,核心思想就是当内存足够时原创 2022-02-16 01:30:00 · 1762 阅读 · 6 评论 -
linux那些事之ZONE(zonelist)(2)
承接《linux内核那些事之ZONE》,一个节点的物理内存被按照需要划分成不同的zone进行管理,而每个节点通过pg_data_t进行管理(想要了解可以参考《linux内核那些事之物理内存模型之SPARSE(3)》,针对NUMA系统而言:每个node节点都有自己的本地内存,因此都有相应自己的pg_data_t和zone管理,同时为了方便整个系统所有node节点上的内存按照zone排布组成了zone list结构。...原创 2022-02-12 02:00:00 · 1192 阅读 · 0 评论 -
linux内核那些事之buddy(2)
Buddy相关API继《linux内核那些事之buddy》,buddy实现主要位于mm\page_alloc.c文件中,对外提供了一系列API:API 作用 struct page * __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid, nodemask_t *nodemask) 按照指定的gfp_mask,申请o...原创 2022-02-08 01:00:00 · 1638 阅读 · 0 评论 -
linux那些事之page fault(do_anonymous_page)(4)
匿名缺页中断是内核中最常见的缺页中断之一,通常在应用程序中对mallo申请到的内存或者是通过mmap申请到的匿名映射内存访问触发的page fault都属于匿名缺页中断。匿名缺页中断会采用系统默认处理方式对缺页中断进程处理,处理匿名缺页中断函数为do_anonymous_page函数do_anonymous_pagedo_anonymous_page函数接口如下:vm_fault_t do_anonymous_page(struct vm_fault *vmf)入参:struct vm原创 2022-02-04 01:00:00 · 1637 阅读 · 0 评论 -
linux那些事之page fault(AMD64架构)(handle_mm_fault)(3)
handle_mm_fault是与架构无关的page fault处理部分,主要是根据发生page fault的虚拟地址和上述步骤查找的对应的vma以及error code转换后的flag具体错误类型进行处理,是内核处理page fault的核心函数,其接口如下:vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address, unsigned int flags)参数原创 2022-02-01 00:45:00 · 4359 阅读 · 2 评论 -
linux那些事之page fault(AMD64架构)(user space)(2)
do_user_addr_fault用户空间地址处理是page fault主要处理流程,x86 64位系统主要是do_user_addr_fault()函数 该处理部分是x86架构特有部分 即与架构有关处理,整个函数处理逻辑过程可以总结为如下图所示:do_user_addr_fault源码/* Handle faults in the user portion of the address space */static inlinevoid do_user_addr_faul..原创 2022-01-26 15:45:45 · 3008 阅读 · 0 评论 -
linux那些事之page fault(AMD64架构)(1)
应用程序或者内核都是运行在虚拟内存空间之中,如果一个虚拟地址要访问物理内存需要通过CPU MMU硬件进行地址转换,整个虚拟地址访问物理内存逻辑过程如下:原创 2022-01-24 10:13:33 · 2080 阅读 · 0 评论 -
linux那些事之early pape fault
由linux那些事之中断与异常(AMD64架构)_2》分析可知,在kernel启动过程中首先安装的early中断dt_setup_early_handler中,主要是对page fault中断支持,这是早期第一个page fault中断处理称为early page fault.early page fault处理的内核空间early page fault主要是为后续用到的虚拟地址空间建立映射方式。需要特别指出的是,此段空间映射采用虚拟地址 与物理地址一一对应映射的方式,主要是方便进行管理,并且此原创 2022-01-15 17:43:28 · 606 阅读 · 0 评论 -
linux那些事之中断与异常(AMD64架构)_2
内核中断初始化过程《中断与异常(AMD64架构)_1》,主要从硬件角度分析amd64 x86 cpu 中的一些基本概念,以及如何配置x86 cpu的中断向量表等。由于中断需要在内核启动较早的时候进行配置,而此时由于一些资源还未初始化完成,因此早期使用的中断处理函数和最终使用的中断处理函数会有差别,根据启动的不同阶段其设置的中断函数也稍微不同。整个内核中断初始化过程也稍微有点复杂,需要梳理内核启动过程才能更加清楚中断初始化为什么这么做:...原创 2022-01-14 17:07:18 · 2106 阅读 · 0 评论 -
linux那些事之中断与异常(AMD64架构)_1
中断与异常中断及异常是学习操作系统必备知识一直,它们是打破当前执行程序流程的一种手段,同时也是cpu与外部硬件交互的一种手段。一般而言中断可以分为可以屏蔽(maskable)和不可屏蔽类型(non-maskable)。按照同步模式划分分为异步和同步中断。同步中断一般是由CPU执行指令时产生,即cpu指令终止执行之后cpu才会发出中断。 异步中断一般时由其他硬件设备产生通知cpu产生的。异常一般是由软件执行时产生错误或者cpu内存执行时产生错误。而在一些特殊情况,比如 debug模式 但单原创 2022-01-07 17:27:41 · 1587 阅读 · 0 评论 -
linux那些事之TLB(Translation-Lookaside Buffer)无效操作
TLB为了加速虚拟地址转换物理地址过程,CPU内部一般都集成TLB硬件单元,通过缓存存取虚拟地址与物理地址映射关系,避免再通过MMU 通过多级查表引入多次内存开销,直接将映射关系存储到硬件单元中,本质上TLB是一种特殊的cache硬件单元。在地址转换过程中,如果TLB中存储有该虚拟地址映射关系,则直接从TLB获取到物理地址,避免通过查表多次引用内存过程。 When paging is enabled, every memory access has its virtual address a..原创 2021-12-29 22:12:35 · 1975 阅读 · 0 评论 -
linux那些事之 page translation(硬件篇)
Page Translation以《AMD64 Architecture Programmer's manual volums》从硬件角度说明一个虚拟地址如何转成对应物理页。AM64 地址转换分为 legacy 和 long mode两个模式,其中legacy x86主要支持将32位虚拟地址转换成32位物理地址(如果开启特殊模式,还支持更大物理内存地址,比如36位或者40 位)。long mode模式下支持将64位虚拟地址转换成52位物理内存地址,long模式下64位系统支持更小的虚拟地址与物理地址..原创 2021-12-27 21:30:50 · 966 阅读 · 0 评论 -
linux那些事之pin memory相关API
内核中为pin memory 用户空间申请物理内存除了get_user_pages() API函数之外,还有其他相关一系列函数,主要位于mm\gup.c 主要都是针对get_user_pages进行的扩展,以满足各种不同需求。pin_user_pagespin_user_pages()为用户空间锁定物理页,与get_user_pages函数基本相同,差别在于gup_flags标志位不同:/** * pin_user_pages() - pin user pages in memory for原创 2021-12-22 21:33:45 · 2497 阅读 · 0 评论 -
linux那些事之follow_page
follow_page()函数是内核中用于根据虚拟地址查找对应的物理页函数,函数定义如下:struct page *follow_page(struct vm_area_struct *vma, unsigned long address, unsigned int foll_flags)参数:struct vm_area_struct *vma: address虚拟地址所属 的vma unsigned long address: 虚拟地址 unsigned int foll_flags.原创 2021-12-20 21:46:09 · 1193 阅读 · 0 评论 -
linux那些事之 page table基本操作
通过遍历page table查找一个虚拟地址已经做了对应的物理内存映射是一个很常用的操作,因此整个walk遍历过程耗时要尽量小。原创 2021-12-17 21:04:54 · 1771 阅读 · 0 评论 -
linux那些事之page table
内核中page table决定了一个虚拟地址如何查找到对应的物理地址关键,维护着整个整个虚拟地址与物理地址对应信息,是实现整个内存虚拟化的基础。在虚拟地址到物理地址的转换过程中为了减少整个物理空间的占用以及解决内存中可能存在的空洞,page table 将一个线性地址(即虚拟地址)按照多级划分的划分,减少转换关系数组占用的物理空间。同时在多级划分过程中,内核为了兼容不同的芯片架构,将整个分级划分进行了抽象处理可以根据不同的架构进行配置,32位系统下支持三级查找,64位系统下支持四级或者五级查找:A p原创 2021-12-14 15:26:54 · 2207 阅读 · 0 评论 -
linux那些事之gup_flags
linux gup子系统在处理各种pin memory中,为了方便处理各种使用场景同时减少代码冗余,使用了gup_flags 标识位用于标记处理内存时各种场景,也是常见的软件设计方法,但是flag引入增加对代码的维护难度,尤其时阅读代码时经常被各种gup_flags(在include\linux\mm.h文件中定义)搞蒙,因此有必要对gup flags做个说明:名称 值 说明 FOLL_WRITE 0x01 用于检查对应的page table entry是否拥有写权限 F原创 2021-12-04 13:10:46 · 1420 阅读 · 0 评论