Linux内核编程
文章平均质量分 66
之内存管理子系统篇
LuckyDog0623
求职ing.....
展开
-
内存管理篇-27寄存器映射:ioremap
驱动在读写寄存器是,需要将寄存器进行ioremap。在x86上,通过专用的指令进行编址访问,但是在arm上是进行统一的编址(占用32位4GB空间的某一小段),因此也叫memory-map的设备。原创 2024-09-19 21:14:33 · 154 阅读 · 0 评论 -
内存管理篇-26虚拟内存管理:vmalloc
vmalloc经常用于申请大块内存。由于kmalloc最大申请内存为4MB,如果想要申请更加大的内存,可以使用vmalloc,大小没有限制,虚拟地址连续,物理地址不一定连续。vmalloc区域最小是240MB,这个是内核定义好的。当线性映射区较小时,会把多余的地址分给vmalloc。kmalloc(最大申请4MB内存,因为它是直接从伙伴系统中申请内存的,伙伴系统中最大的内存块就是4MB)vmalloc:申请的物理页帧是不是连续的,虚拟地址空间是已连续的。原创 2024-09-18 21:28:36 · 349 阅读 · 0 评论 -
内存管理篇-23 二级页表的创建过程-上
采用一级section映射的时候,页表项的每个entry都是某物理区间section的起始地址。采用二级映射后,这里的内容就发生了变化,每个entry的内容将保存的是二级页表的起始地址,二级页表entry中的内容才是真正的保存了物理页帧的起始地址。二级页表的填充过程:一级页表是4096项(用虚拟地址高12位),二级页表是256项(用虚拟地址中间10位,每个项能代表一个物理页,因此4KB*256=1MB)。,因为第二级页表只有10位。没看懂,二级页表是如何创建的,如何复用之前内核镜像前的16KB页表空间的!原创 2024-09-12 22:48:46 · 377 阅读 · 0 评论 -
内存管理篇-22 高端内存和低端内存的分界线
如果配置3:1,3GB+760MB为线性映射区。如果2:2划分,2+1760MB为线性映射区。高端内存没啥用,都没人用了,64位地址的虚拟空间特别大,再大的物理内存也能直接映射。当ddr为256MB时,256MB都是低端内存。剩下的1776MB虚拟内存即使访问了,本质上还是被映射到了低端内存。当ddr为512MB时,512还是全部都是低端内存。当ddr为1GB时,低端内存为1024GB,vmalloc区别变成1008MB。重点是啥:观察配置内核和用户空间的比例为不同值,设置ddr的大小为不同值的情况下。原创 2024-09-05 21:59:51 · 424 阅读 · 0 评论 -
内存管理篇-21 虚拟内存管理:线性映射区
这部分讲线性映射区的内容。一般老的嵌入式平台,它内存很小只有几百兆,都会直接把整个物理内存映射到线性映射区了,只有当物理内存大于1GB以上,线性映射区无法cover的时候就把剩下的放到高端内存。所以这个区域是最简单的。线性映射区一般是指内核空间的某个部分,直接映射到低端内存的区域。并且他们之间是线性映射的。PAGE_OFFSET就是内核的起始地址,如果配置内核用户空间是1:3的话,就是0xc0000000。如果配置2:2的话就是0x80000000;线性映射区的大小是可以配置的,原创 2024-09-05 21:38:32 · 233 阅读 · 0 评论 -
内存管理篇-20 Linux虚拟内存管理
这里的内容比较少。只要就是内核用户空间的划分。内核空间又有自己的划分。也需要注意一下每个区域的性能。理论上线性映射是最简单的,所以性能最高。同时,注意内核空间是可以配置的,并不是都3:1。原创 2024-09-02 17:15:01 · 360 阅读 · 0 评论 -
内存管理篇-19 TLB和Table wake unit
当 TLB 满时,需要采用某种替换策略来决定哪些页表项需要被替换掉。TLB 是一种高速缓存,用于存储最近使用的页表项(Page Table Entries, PTEs)。它的主要目的是加速虚拟地址到物理地址的转换过程。:当 TLB 中没有对应的页表项时,需要访问主内存中的页表来查找物理地址,并将找到的页表项加载到 TLB 中。:当虚拟地址的页号(Page Number)在 TLB 中找到对应的页表项时,可以直接从中获取物理地址。TLB的工作机制:通过asid区分是哪个进程的虚拟地址。原创 2024-09-01 15:18:51 · 192 阅读 · 0 评论 -
内存管理篇-18解开页表的神秘面纱-下
首先去掉后20位(1MB大页映射,页内偏移为 1MB)得到index为0x801,接着去page table找到第0x801项entry,(此时page table也是在内存上的一部分空间,是按照字节编址,但是每个单位是4字节,因此第0x801项就是0x801*4字节=0x2004的物理地址所在的地方。通过这一计算,我们得到的是内核镜像在虚拟地址空间中的起始位置。通过将r6(内核镜像的虚拟地址结束位置)向右移位(lsr),并加上r4(页目录的基地址),得到内核镜像在页表中的最后一个条目的地址。原创 2024-09-01 13:01:40 · 994 阅读 · 0 评论 -
内存管理篇-17解开页表的神秘面纱-上
-好像并没有解开。。原创 2024-09-01 11:20:59 · 378 阅读 · 0 评论 -
内存管理篇-16二级页表工作原理
上节课的页表的一级页表其实并不完全正确,一般虚拟页帧和物理页帧号不会都占用实际字段,这样毕竟很浪费内存。原创 2024-08-31 15:28:14 · 451 阅读 · 0 评论 -
内存管理篇-15虚拟地址和MMU工作原理
隔了两天再更新。。。周四下班太晚。周五出去吃夜宵回来太晚。。。原创 2024-08-31 13:31:57 · 983 阅读 · 0 评论 -
内存管理篇-14kmalloc机制实现分析
引入这个kmalloc的目的,是因为前面的slab接口太过于复杂,因此需要一个全新的封装kmalloc接口,内存申请编程接口实现。kmalloc底层起始也是基于slab缓存实现的。原创 2024-08-28 21:14:54 · 1012 阅读 · 0 评论 -
内存管理篇-13slab、slob和slub分配器
slab机制是对伙伴系统的补充和改进,主要是因为伙伴系统的粒度最小是页,需要进一步细化粒度,因此引入了slab机制。slab机制从伙伴系统统申请到页后,进行切割成大小相同的free object。图中特意举例了tash_struct inode_cache kmalloc-1k几个场景,是由于他们在内核中会频繁的申请和释放,因此内核需要一个这样的小的且不同的大小的内存释放申请机制。于是就有了slab slob slub分配器。Slab 分配器。原创 2024-08-27 23:42:05 · 962 阅读 · 0 评论 -
内存管理篇-12伙伴系统初始化四:CMA内存释放
CMA内存也是reserved内存保留的一部分,也是属于保留的一部分。前面我们已经讲到,cma区域在未使用状态下是会释放到伙伴系统的。在前面两节,首先把memblock的memory这部分释放,然后把reserved中的init释放,接下来在讲讲如何将cma的释放。当内核看到设备树中有dma,cma-default, nomap,reusable这些字段是,大概率是dma专用的区域。内核不会把这个区域放到伙伴系统中。原创 2024-08-27 21:51:16 · 219 阅读 · 0 评论 -
内存管理篇-11伙伴系统初始化三:init内存释放
上节课我们把前期的内存管理系统的memblock.free区域释放到内存伙伴系统了,这节课要介绍一下memblock的reserved区域。这片区域由不同的驱动直接操作它,各自dma 映射等等操作。上节的操作中,只是把这片区域设置为reserved属性,并没有做其他操作。底下是几个常见的reserved内存区域:然后就依次介绍每个阶段:(1)init代码段的释放过程:注意:解释一下函数如果被__init修饰了之后,代表把这个函数代码段放在'init.text'段。原创 2024-08-26 21:45:34 · 254 阅读 · 0 评论 -
内存管理篇-10伙伴系统初始化二:memblock内存释放
memblock初始化之后,此时有两个结构体记录了所有的区域。原创 2024-08-26 21:24:14 · 279 阅读 · 0 评论 -
内存管理篇-09伙伴系统初始化一:memblock管理
计算机加电后进行硬件检测。加载引导程序,将Linux内核加载到内存中。:内核被加载后开始初始化各个子系统。进行CPU架构相关的初始化。初始化内存控制器和其他设备驱动。在内核初始化的过程中,会调用mm_init函数来初始化内存管理系统。mm_init函数会初始化包括伙伴系统在内的各种内存管理组件。mm_init将由初始内存分配器(如memblock allocator)管理的内存空间释放到伙伴系统中内核就可以使用伙伴系统来管理物理内存的分配和回收。原创 2024-08-25 15:37:17 · 910 阅读 · 0 评论 -
内存管理篇-08连续内存分配器CMA
DMA区域会极大的浪费内存的使用,因为即使DMA没有人使用,DMA区域也会空在这里,因此引入CMA解决这种问题。为了解决既不浪费内存,又能申请到连续的物理内存空间,在嵌入式中引入了CMA的概念。CMA区域和DMA功能一样,专门用于DMA或者其他功能。只有当dma或者其他模块需要连续大块内存的时候,它才会分配出一个CMA区域。原创 2024-08-25 10:51:35 · 668 阅读 · 0 评论 -
内存管理篇-07页分配器接口-alloc_page
----终于到了编码实战阶段了,前面都是在将思想和实现机制,即使看了源代码还是模模糊糊,不够清晰。本节通过内核接口从伙伴系统进行申请和释放内存。其实很多缓存机制最终都是通过伙伴系统申请一大片内存,然后内部再进行对这些页处理优化。伙伴系统提供了free_page和alloc_pages两个函数进行申请和释放内存,至于函数内部的实现机制,这里还没开始讲,主要讲了如何使用。原创 2024-08-24 17:07:34 · 363 阅读 · 0 评论 -
内存管理篇-06Per-CPU页帧缓存
是一种缓存机制,对伙伴系统的完善。由于伙伴系统管理的页面都是全局的,每个进程在申请页面的时候都需要加锁解锁等操作,极大的引入了开销。为了提高效率就引入页帧缓存,为每个cpu提供一个变量指针__percpu *pageset(定义在struct zone),这样每个cpu就不用去加锁解锁申请,直接使用本地物理页面。把单个物理页面的申请和释放做成缓存,每个cpu都有这个链表。给每个cpu本地定义一个页表,维护这样一个变量。因此,不需要去全局伙伴系统上去申请释放。原创 2024-08-24 15:37:33 · 479 阅读 · 0 评论 -
内存管理篇-05物理页面的迁移类型migratetype
本节内容依旧是对上节课伙伴系统的补充,主要介绍了新版伙伴系统的页面迁移相关的内容为什么要引入页面迁移类型?新版本伙伴系统针对老版本的伙伴系统的升级改进。主要优化memory compaction内存碎片整理的过程。页面迁移实际上就是伙伴系统中free_area[MAX_ORDER]结构体保存的链表指针将链表分类,如上图所示。并且页面在申请的时候也去考虑它的类型。将不可移动的放一块,可移动的放一块等等;原创 2024-08-24 13:00:54 · 363 阅读 · 0 评论 -
内存管理篇-04伙伴系统
首相将系统中的内存分为大小不同的物理块,对于物理地址相连的物理页合并成大的物理块,对于相同大小的物理块用链表连接起来,通过一个struct free_area free_are[MAX_ORDER]保存,每个元素都指向一个链表(他们内存块大小不一样)。相反,如果用户释放内存,如果发现释放后的page和旁边的相连,就会逆向的把它合并在一起。对每个free_area[order]进行分类,观察哪些是可移动的,不可移动的,可回收的,预留的,隔离的以及CMA等等。首先,伙伴系统的实现是基于分区zone的实现的。原创 2024-08-24 12:40:50 · 266 阅读 · 0 评论 -
内存管理篇-03物理内存管理-32位
正片从现在开始了。原创 2024-08-24 01:40:14 · 798 阅读 · 0 评论 -
内存管理篇-02内存硬件电路和接口
通过D触发器构建寄存器和内存的结构对比,这里主要先表达sram复杂,dram简单。原创 2024-08-23 21:29:09 · 233 阅读 · 0 评论 -
内存管理篇-01内存管理学习概述
内存管理相关知识:为什么要分为虚拟内存和物理内存? 用户空间,内核空间 物理地址,虚拟地址 页表是什么?谁在维护?存在哪里?什么格式? mmu,tlb 映射:文件映射,匿名映射,io内存映射 驱动如何申请内存? 面试:缺页中断,伙伴系统本期课程主要内容:物理内存管理: zone, page 伙伴系统 虚拟内存管理 mmu,页表,tlb 内存申请与释放接口 映射机制底层实现 预期收获:物理内存,虚拟内存的划分 深入理解页表,地址转换,映射 学会使用内核提供的接口申请内原创 2024-08-23 21:07:29 · 210 阅读 · 0 评论