![](https://img-blog.csdnimg.cn/20190927151053287.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
Linux内核-内存管理
文章平均质量分 72
Linux内核基于S3C2440内存管理机制
生活需要深度
这个作者很懒,什么都没留下…
展开
-
内存屏障:解密Linux内核神器的秘密功效与应用方法
现在大多数现代计算机为了提高性能而采取乱序执行,这可能会导致程序运行不符合我们预期,内存屏障就是一类同步屏障指令,是CPU或者编译器在对内存随机访问的操作中的一个同步点,只有在此点之前的所有读写操作都执行后才可以执行此点之后的操作。内存屏障,也称内存栅栏,内存栅障,屏障指令等, 是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作。大多数现代计算机为了提高性能而采取乱序执行,这使得内存屏障成为必须。原创 2024-07-03 20:19:45 · 758 阅读 · 0 评论 -
深入浅出 Linux 中的 ARM IOMMU SMMU III
在前面 IOMMU 回调 arm_smmu_domain_alloc() 被调用创建 domain 时,如果 domain type 为 IOMMU_DOMAIN_DMA,会为 domain 创建类型为 IOMMU_DMA_IOVA_COOKIE 的 iommu_dma_cookie 及其 struct iova_domain。iommu_setup_dma_ops() 函数调用 iommu_dma_init_domain() 初始化 DMA 映射 domain,并为系统 I/O 设备设置 DMA 操作。原创 2024-06-27 11:48:52 · 123 阅读 · 0 评论 -
Linux内存细节 bootmem_bootmap_pages与find_bootmap_pfn
本身boot中给定的bootmap这个bit位标定page使用情况需要一个位置来存储,两个函数bootmem_bootmap_pages用来计算当前管理的内存页数目需要多大的内存用来保存bit位。find_bootmap_pfn用来找到这个位置对应的pfn。这个位置关键变量打印结果:bootmem_bootmap_pages start_pfn=0x30000, end_pfn=0x34000, boot_pages=0x1, boot_pfn=0x303cf具体放置位置find_bootmap_原创 2022-04-08 18:19:16 · 270 阅读 · 0 评论 -
Linux内存细节 request_standard_resources
文章来源:http://gliethttp.cublog.cn在分析request_standard_resources前先来看linux对挂接在4G总线空间上的设备实体的管理方式-resource结构体 一个独立的挂接在cpu总线上的设备单元,一般都需要一段线性的地址空间来描述设备自身,linux是怎么管理所有的这些外部"物理地址范围段",进而给用户和linux自身一个比较好的观察4G总线上挂接的一个个设备实体的简洁、统一级联视图的呢? linux采用struct resource结构体来描述一..原创 2022-04-05 08:41:08 · 2523 阅读 · 0 评论 -
Linux内存细节 reserve_node_zero
假如内存的物理起始地址为:0x30000000, 大小为:0x1000000void __init reserve_node_zero(pg_data_t *pgdat){ unsigned long res_size = 0; /* * Register the kernel text and data with bootmem. * Note that this can only be in node 0. */#ifdef CONFIG_XI...原创 2022-04-04 19:48:07 · 91 阅读 · 0 评论 -
Linux内存细节 reserve_bootmem_node
假如内存的物理起始地址为:0x30000000, 大小为:0x1000000int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, unsigned long size, int flags){ unsigned long start, end; start = PFN_DOWN(physaddr);//0x30431 end = PFN_UP(p...原创 2022-04-04 19:42:36 · 96 阅读 · 0 评论 -
Linux内存细节 free_bootmem_node
假如内存的物理起始地址为:0x30000000, 大小为:0x1000000void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, unsigned long size){ unsigned long start, end; //空函数 kmemleak_free_part(__va(physaddr), size); start = PF...原创 2022-04-04 19:38:09 · 79 阅读 · 0 评论 -
Linux内存细节 free_area_init_node
在对free_area_init_node()函数分析之前,我们也要看看它的源头,这个函数的调用过程如下start_kernel()->paging_init()->free_area_init_node(),我们来看看在调用这个函数之前,在paging_init()前面的语句做了些什么。 /* * initialise the zones within each node */ for (node = 0; node < numnodes; node++) {un...原创 2022-04-04 19:52:00 · 583 阅读 · 0 评论 -
Linux内存细节 create_mapping - linux内核MMU地址映射
create_mapping核心在初始化建立的section一级map基础上面完成入参物理地址到虚拟地址的映射。本文描述的是关于MINI2440开发板上的SDRAM的内存映射(bootmem阶段)硬件的基本参数为:起始物理地址:0x30000000物理内存大小:0x1000000 [16MB]那么基于以上信息,在初始化过程中下面的变量已经被赋为如下的值:bank.start = 0x30000000bank.size = 0x1000000[16MB]通过阅读代码可以知道,在创建内..原创 2022-04-04 18:46:48 · 609 阅读 · 0 评论 -
Linux内存细节 build_mem_type_table与prepare_page_table
/* * Adjust the PMD section entries according to the CPU in use. */static void __init build_mem_type_table(void){ struct cachepolicy *cp; unsigned int cr = get_cr(); unsigned int user_pgprot, kern_pgprot; int cpu_arch = cpu_architecture(); int i;.原创 2022-04-08 08:21:51 · 280 阅读 · 0 评论 -
Linux内存细节 初始化(八) 至kswapd_init
至此,内存初始化部分已看完,遗留问题:1、对于unicore或者mips的页表建立都很清楚,但是对于ARM我不清楚: 初始化部分涉及的页表映射建立,我都以unicore架构为准,ARM的页表映射从原理上讲easy,问题在于ARM的页表中没有引入Dirty、Accessed位,因此,对于如何在基于ARM架构的Linux系统上实现页回收就有些疑问,上次和同学看下代码,ARM使用了软件的方法解决了该问题,但是具体方法自己并不清楚. 当然对于新的ARM架构可能在页表项上已支持Dirty、...原创 2022-04-09 17:56:19 · 236 阅读 · 0 评论 -
Linux内存细节 vmalloc_init 及 ioremap - linux内存管理(六)
是不是我错了,本想这个函数会如网上所说将进行非连续内存管理的初始化,但是对于2.6.34的ARM架构而言,该函数实际完成的业务非常少。内存管理的初始化读到此处,我感觉原有的认识存在很大缺陷:(1)内核空间的下限是3G吗?永久映射的PKMAP_BASE已在3G下;(2)低端内存是896M吗?2.6.32的omap4430的VMLLOC_END是1G - 128M,VMALLOC_MIN是1G - 128M -128M;(3)还存在固定映射吗?FIXADDR_SIZE的空间已被FIX_K...原创 2022-04-09 17:52:41 · 273 阅读 · 0 评论 -
Linux内存细节 build_all_zonelist
看到了mm_init(),期间将从bootmem迁移到伙伴系统,slab分配器也会建立。在分析mm_init()之前,把setup_arch(&command_line)之后的函数分析了以下,详见注释。start_kernel() |---->page_addr...原创 2022-04-09 17:34:23 · 218 阅读 · 0 评论 -
Linux内存细节 kmem_cache_init初始化slab分配器
看了下kmem_cache_init,涉及到不同MIGRATE间的buddy system的迁移,kmem_cache的构建,slab分配器头的构建、buddy system的伙伴拆分。对于SMP系统,每个kmem_cache还有各个CPU的arraycache_init,这样每个CPU可以从各自的arraycache_init中获取缓存,如果不足,则从slab分配器中获得;当让slab分配器的三条链表也有一定的缓存作用,如果三条链表都已空了,则需要从buddy system中申请页。在申请页的时候,由原创 2022-04-09 17:44:36 · 606 阅读 · 0 评论 -
Linux内存细节 mem_init bootmem迁移至伙伴系统
mm_init中执行mem_init,将原通过bootmem分配器管理的低端内存 及 通过meminfo得知的高端内存释放到伙伴系统中,最后bootmem位图本身占用的低端内存物理页也被释放进伙伴系统,当然对于内核、初始页表、pkmap页表、struct page实例、ramdisk、percpu变量、dentry_hashtable、inode_hash_table已经被占用的区域不会被释放(对于内核开始的一段,后面会释放).start_kernel() .原创 2022-04-09 17:27:19 · 631 阅读 · 0 评论 -
Linux内存细节 内核临时页表 - linux内存管理(二)
在分析__create_page_tables函数之前,需要知道以下的知识。1、head.S首先确定了processor type和machine type,之后就是创建页表。通过前面的两步,我们已经确定了processor type和machine type。此时,一些特定寄存器的值如下所示:r8 = machine info(struct machine_desc的基地址)r9 = cpu id(通过cp15协处理器获得的cpu id)r10...原创 2022-03-29 12:07:02 · 782 阅读 · 0 评论 -
linux内存细节 内存管理初始化概述
在内存管理的上下文,初始化可以有多重含义。在许多CPU上,必须显式设置适用于Linux内核的内存模型。文章给出了linux系统设计的初始化阶段设计的内存接口与函数。1. 基本概念1.1. linux内存管理的层次结构linux把物理内存划分为三个层次来管理,分别是存储节点,管理区和页面。层次 描述 存储节点(Node) CPU被划分为多个节点(node),内存则被分簇,每个CPU对一个本地物理内存,即一个CPU-node对应一个内存簇bank,即每个内存簇被认为是一个节点原创 2022-04-04 15:08:09 · 1310 阅读 · 0 评论 -
一次解决Linux内核内存泄漏实战全过程
主要用来跟踪kmalloc()和kfree()函数对应的trace event, 因为他们的trace event被触发之后会打印kmalloc()和kfree()所申请和释放的内存地址,然后进一步只过滤申请4096字节的情况。PSS:按比例报告的物理内存,比如进程A占用20M物理内存,进程B和进程A共享5M物理内存,那么进程A的PSS就是(20 - 5) + 5/2 = 17.5M。发现从上面几个ptr内存中读出的内容都是非常相似,仔细看一下发现都是/proc/schedstat 的输出内容。原创 2023-03-07 18:16:39 · 630 阅读 · 0 评论 -
Linux为什么一定要copy_from_user ?
网上很多人提问为什么一定要copy_from_user,也有人解答。比如百度一下:但是这里面很多的解答没有回答到点子上,不能真正回答这个问题。我决定写篇文章正式回答一下这个问题,消除读者的各种疑虑。这个问题,我认为需要从2个层面回答个层次是为什么要拷贝,可不可以不拷贝?第二个层次是为什么要用copy_from_user而不是直接memcpy拷贝这个事情是必须的,这个事情甚至都跟Linux都没有什么关系。传给dev_set_name()的根本是个stack区域的临时变量,是一个匆匆过客。原创 2023-02-24 11:40:35 · 1221 阅读 · 0 评论 -
Linux I/O 原理和零拷贝( zero-copy )技术原理详解
零拷贝就是一种避免 CPU 将数据从一块存储拷贝到另外一块存储的技术。针对操作系统中的设备驱动程序、文件系统以及网络协议堆栈而出现的各种零拷贝技术极大地提升了特定应用程序的性能,并且使得这些应用程序可以更加有效地利用系统资源。这种性能的提升就是通过在数据拷贝进行的同时,允许 CPU 执行其他的任务来实现的。零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率。原创 2023-06-02 10:39:25 · 575 阅读 · 0 评论 -
Linux:动态库的加载原理和与进程的知识整合
答案是有的,这是因为当程序被编译之后,所有的函数名变量名等等内容,都不再会存在,取而代之的是一个一个的地址,从汇编代码的角度来讲,每一步的跳转背后都是一个一个的地址,比如当前在函数的内部定义了一个临时变量,这个临时变量是在栈区存在的,但是此时可执行程序中可并没有栈,栈是在程序加载到内存中运行的时候才有栈区的概念,但是不影响,这个变量是在函数的内部形成的,这也就意味着在形成变量的时候,是通过寄存器为出发点,再加上偏移量,就可以进行访问,所以最终函数名变量名都是地址了。为什么叫做共享库呢?原创 2024-03-20 09:07:42 · 994 阅读 · 0 评论 -
Linux内存管理 CMA大段设备
在我们使用ARM等嵌入式Linux系统的时候,一个头疼的问题是GPU,Camera,HDMI等都需要预留大量连续内存,对于内核如果申请一块连续的内存空间该怎么处理呢?首先向到的是利用内核提供的kmalloc申请,尽管kmalloc可以申请连续的内存空间,但是在长时间的测试中,会出现内存空间可能申请失败的情况,无法保证能成功分配。使用memblock分配器中提供的方法,称为预留内存,但这么预留的内存只能被特定的Device驱动所使用,System不能分配这部分内容,会导致内存浪费因此,内核设计者设计了原创 2022-04-12 20:35:31 · 1803 阅读 · 0 评论 -
Linux内存管理 RMAP
RMAP反向映射是一种物理地址反向映射虚拟地址的方法。映射页表用于虚拟地址到物理地址映射,其中的PTE页表项记录了映射关系,同时结构体中的mapcount字段保存了有多少PTE页表项映射了该物理页。反向映射当某个物理地址要进行回收或迁移时,此时需要去找到有多少虚拟地址射在该物理地址,并断开映射处理。在没有反向映射的机制时,需要去遍历进程的页表,这个效率显然是很低下的。反向映射可以找到虚拟地址空间VMA,并仅从VMA使用的用户页表中取消映射,可以快速解决这个问题。kswapd。原创 2024-04-10 17:33:23 · 381 阅读 · 0 评论 -
Linux内存管理 vma/malloc/mmap
vma;malloc;mmap;进程地址空间中,我们常见的代码段,数据段,bss段等,实际上都是一段地址空间区域。Linux将地址空间中的区域称为, 简称VMA,使用来描述。在进行内存申请和映射时,都会去地址空间中申请一段虚拟地址区域,而这部分操作也与vma关系密切,因此本文将三个放到一块来进行分析。开启探索之旅吧。原创 2022-04-28 16:22:12 · 4230 阅读 · 0 评论 -
Linux内存管理 vmap/vmalloc/ioremap
前面我们学习了linux内核中对于物理上连续的分配方式,采用伙伴系统和slub分配器分配内存,但是我们知道物理上连续的映射是最好的分配方式,但并不总能成功地使用。在分配一大块内存时,可能竭尽全力也无法找到连续的内存块。针对这种情况内核提供了一种申请一片连续的虚拟地址空间,但不保证物理空间连续,也就是vmalloc接口。vmalloc的工作方式类似于kmalloc,只不过前者分配的内存虚拟地址连续,而物理地址则无需连续,因此不能用于dma缓冲区通过vmalloc获得的页必须一个一个地进行映射,效率不高,原创 2022-04-14 08:52:15 · 855 阅读 · 0 评论 -
Linux内存管理 页面置换算法
为了提高内存的利用率,解决内存供不应求的问题,更加合理的使用内存,引出了虚拟内存的概念。系统将内存暂时不需要的部分写入到硬盘,实现了对于扩展内存容量,所以叫虚拟内存,使得应用程序可以使用比实际物理内存更大的内存空间。前面我们了解了在进程运行过程中,当内存中存在空闲页的时候,系统如何实现这个虚拟内存管理的软硬件实现方式。如果内存中没有空闲页,那么就需要页面的调出,算法的好坏直接影响到系统的性能,本章的主要内容就是基于页面置换算法,其主要内容包括置换算法的功能和目标有哪些页面置换算法,各个算法的优缺点l原创 2022-04-12 12:29:12 · 1600 阅读 · 1 评论 -
Linux内存管理 slub分配器
内核管理页面使用了2个算法:伙伴算法和slub算法,伙伴算法以页为单位管理内存,但在大多数情况下,程序需要的并不是一整页,而是几个、几十个字节的小内存。于是需要另外一套系统来完成对小内存的管理,这就是slub系统。slub系统运行在伙伴系统之上,为内核提供小内存管理的功能。 slub把内存分组管理,每个组分别包含 8、64、512、…2048个字节,在4K页大小的默认情况下,另外还有两个特殊的组,分别是96B和192B,共11组。之所以这样分配是因为如果申请2^12B大小的内存,就可以使用伙伴系统提供原创 2022-04-14 08:41:50 · 1890 阅读 · 1 评论 -
Linux内存管理 - 页框分配器2 watermark/compaction/reclaim
在内核初始化完成后,内存管理的责任由伙伴系统承担。前面一章主要学习了伙伴系统的软件算法实现原理伙伴系统原理,本章正式开始Linux下伙伴系统的学习,本章主要是原理性的梳理一些流程,其主要包括linux对于伙伴系统的设计思路内存碎片的问题和分配器如何处理碎片伙伴系统的分配器API1. 设计思路前面章节中学习了伙伴系统原理,我们重新梳理伙伴系统的核心思路:内核将系统的空闲页面分成11个块链表,每个块链表分别管理着1,2,4,8,16,32,64,128,256,512和1024个物理页帧号,每个页面原创 2022-04-13 15:51:35 · 3344 阅读 · 0 评论 -
Linux内存管理 - 页框分配器1
一:nginx源码总述winrar二:nginx源码查看工具visual studio,source Insight,visual stuido Code.采用 Visual Studio Code来阅读nginx源码 Visual Studio Code:微软公司开发的一个跨平台的轻量级的编辑器(不要混淆vs2017:IDE集成开发环境,以编译器); Visual Studio Code在其中可以安装很多扩展模块; 1.30.0版本,免费的,多平台;官...原创 2022-04-28 21:09:15 · 2640 阅读 · 0 评论 -
Linux内存管理 内存模型与zone_sizes_init
在(四)Linux内存模型之Sparse Memory Model中,我们分析了函数的上半部分,这次让我们来到下半部分吧,下半部分主要是围绕函数展开。前景回顾:{/**/}在Linux中,物理内存地址区域采用zone来管理。不打算来太多前戏了,先上一张的函数调用图吧:需要再说明一点是,使用的是ARM64,UMA(只有一个Node),此外,流程分析中那些没有打开的宏,相应的函数就不深入分析了。开始探索吧!原创 2023-01-01 20:02:23 · 532 阅读 · 0 评论 -
Linux内存管理 Bootmem管理器
Bootmem机制是内核在启动时对内存的一种简单的页面管理方式。它为建立页表管理代码中的数据结构提供动态分配内存的支持,为了对页面管理机制作准备,Linux使用了一种叫bootmem分配器(bootmem allocator)的机制,这种机制仅仅用在系统引导时,它为整个物理内存建立起一个页面位图。这个位图建立在内核代码映象终点_end上方的地方。这个位图用来管理低区(可被直接一一映射的物理内存区,小于896Mb)。原创 2022-04-04 19:44:52 · 721 阅读 · 0 评论 -
Linux内存管理 paging_init解析
从(二)Linux物理内存初始化中,可知在调用之前,存放和DTB的两段物理内存区域可以访问了(相应的页表已经建立好)。尽管物理内存已经通过添加进系统,但是这部分的物理内存到虚拟内存的映射还没有建立,可以通过分配一段物理内存,但是还不能访问,一切还需要等待的执行。最终页表建立好后,可以通过虚拟地址去访问最终的物理地址了。按照惯例,先上图,来一张ARM64内核的内存布局图片吧,最终的布局如下所示:开启探索之旅吧!原创 2023-01-01 19:36:08 · 563 阅读 · 0 评论 -
Linux内存管理 fixup或parse_tags物理内存解析 - linux内存管理(四)
在2.4(具体哪个版本记不清了)以后的Linux内核中引入了一种新的向内核传递参数的方法tag标记。内核参数通过一个静态的tag链表在启动的时候传递到内核。每个tag的结构为+-----------+tag_header+-----------+ tag_xxx+-----------+其中...原创 2022-04-08 10:17:10 · 920 阅读 · 0 评论 -
Linux内存管理 DMA/SGDMA/RDMA
(1)程序控制输入输出方式。完全由的输入输出方式,每发送或接收一个数据都要由CPU执行相应的指令才能完成;与CPU异步工作;适合于连接低速外围设备。(2)中断输入输出方式。当出现来自系统外部,机器内部,甚至处理机本身的任何例外的,或者虽然是事先安排的,但出现在现行程序的什么地方是事先不知道的事件时,CPU暂停执行现行程序,转去处理这些事件,等处理完成后再返回来继续执行原先的程序;与CPU并行工作;数据的输入和输出都要经过CPU;一般用于连接低速外围设备。(3)方式(DMA)。外围设备与。原创 2023-02-20 13:36:23 · 1144 阅读 · 0 评论 -
Linux内存管理 Cache
SMMU(system mmu),是I/O device与总线之间的地址转换桥。它在系统的位置如下图:它与mmu的功能类似,可以实现地址转换,内存属性转换,权限检查等功能。2. 为什么需要SMMU?了解SMMU出现的背景,需要知道系统中的两个概念: DMA和虚拟化。DMA:((Direct Memory Access),直接内存存取, 是一种外部设备不通过CPU而直接与系统内存交换数据的接口技术。原创 2023-07-11 21:09:46 · 1383 阅读 · 0 评论 -
Linux内存管理 MMU/IOMMU/SMMU
要想理解好Linux的页表映射,MMU的机制是需要去熟悉的,因此将这两个模块放到一起介绍。。MMU:完成的工作就是虚拟地址到物理地址的转换,可以让系统中的多个程序跑在自己独立的虚拟地址空间中,相互不会影响。程序可以对底层的物理内存一无所知,物理地址可以是不连续的,但是不妨碍映射连续的虚拟地址空间。TLBMMU工作的过程就是查询页表的过程,页表放置在内存中时查询开销太大,因此专门有一小片访问更快的区域用于存放地址转换条目,用于提高查找效率。当页表内容有变化的时候,需要清除TLB,以防止地址映射出错。原创 2023-01-01 19:11:04 · 15038 阅读 · 0 评论 -
Linux内存管理教程
“一直以来,我都非常着迷于两种电影拍摄手法:一种是慢镜头,将每一个细节全方位的展现给观众。另外一种就是快镜头,多半是反应一个时代的变迁,从非常长的时间段中,截取几个典型的snapshot,合成在十几秒的镜头中,可以让观众很快的了解一个事物的发展脉络。对应到技术层面,慢镜头有点类似情景分析,把每一行代码都详细的进行解析,了解技术的细节。快镜头类似数据流分析,勾勒一个过程中,数据结构的演化。本文采用了快镜头的方法,对内存初始化部分进行描述,不纠缠于具体函数的代码实现,只是希望能给大家一个概略性的印象(有兴趣的同原创 2022-04-02 16:13:12 · 1309 阅读 · 2 评论