Android OpenGL ES详解——模板Stencil
目录
一、概念
1、模板测试
2、模板缓冲
二、模板测试如何使用
1、开启和关闭模板测试
2、开启/禁止模板缓冲区写入
3、模板测试策略函数
4、更新模板缓冲
5、模板测试应用——物体轮廓
三、模板缓冲如何使用
1、创建模板缓冲
2、使用模板缓冲
3、模板缓冲应用——描边
四、源码下载
一、概念
1、模板测试
在OpenGL中,模板测试(Stencil Testing)是一种用于控制像素绘制的方式。它允许开发者根据模板缓冲区(Stencil Buffer)中的值来决定是否绘制某个像素。模板测试通常用于实现一些高级的图形效果,如阴影、反射、折射等。
当片段着色器处理完片段之后,模板测试(Stencil Test) 就开始执行了,和深度测试一样,它能丢弃一些片段。仍然保留下来的片段进入深度测试阶段,深度测试可能丢弃更多。模板测试基于另一个缓冲,这个缓冲叫做模板缓冲(Stencil Buffer),我们被允许在渲染时更新它来获取有意思的效果。
模板测试与深度测试类似,但在渲染管线中发生在深度测试之前。模板测试也会丢弃掉一些片段,只是丢弃的片段数量比深度测试少。
2、模板缓冲
模板测试是基于一个缓冲区 -- 模板缓冲区(stenci buffer),同理该缓冲区也是由我们创建窗口库创建的,我使用的库是GLFW库。
模板缓冲中的模板值(Stencil Value)通常是8位的,因此每个片段/像素共有256种不同的模板值(译注:8位就是1字节大小,因此和char的容量一样是256个不同值)。这样我们就能将这些模板值设置为我们链接的,然后在模板测试时根据这个模板值,我们就可以决定丢弃或保留它了。
StencilBuffer是模板缓冲,可以用来实现一些诸如描边,遮罩之类的操作。
模板测试和深度测试作用类似,模板测试主要是通过对比模板缓冲区来决定是否需要对片段进行丢弃。
在渲染时更新模板缓冲区可以获取很多有趣的效果。
一个模板缓冲区通常使用8位来表示,因此一个像素可以有256中表示方法。
每个窗口库都需要为你设置模板缓冲。GLFW自动做了这件事,所以你不必告诉GLFW去创建它,但是其他库可能没默认创建模板库,所以一定要查看你使用的库的文档。(GLFW 是一个 OpenGL 的应用框架,支持 Linux 和 Windows。GLFW 主要用来处理特定操作系统下的特定任务,例如 OpenGL 窗口管理、分辨率切换、键盘、鼠标以及游戏手柄、定时器输入、线程创建等等。)
上面图示中:首先要使用模板测试,必须先开启glEnabIe(GL STENCIL TEST),然后先使用0来清空模板缓冲区,然后开启矩形片段用1填充,此时我们将1写入模板缓冲区,绘制出来的图形只会显示模板缓冲区为1的像素图形。
模板测试就是通过模板缓冲中记录的模板信息实现的,具体来说就是渲染管线在模板缓冲区中为每个位置的片元保存了一个“模板值”,当像素需要进行模板测试时,将设定的模板参考值与该片元对应位置的模板值进行比较,符合条件的片元通过测试,不符合条件的则被丢弃,不进行渲染;
二、模板测试如何使用
无论我们在渲染哪里的片段,模板缓冲操作都允许我们把模板缓冲设置为一个特定值。改变模板缓冲的内容实际上就是对模板缓冲进行写入。在同一次(或接下来的)渲染迭代我们可以读取这些值来决定丢弃还是保留这些片段。当使用模板缓冲的时候,你可以随心所欲,但是需要遵守下面的原则:
- 开启模板缓冲写入。
- 渲染物体,更新模板缓冲。
- 关闭模板缓冲写入。
- 渲染(其他)物体,这次基于模板缓冲内容丢弃特定片段。
使用模板缓冲我们可以基于场景中已经绘制的片段,来决定是否丢弃特定的片段。
1、开启和关闭模板测试
你可以开启GL_STENCIL_TEST
来开启模板测试。接着所有渲染函数调用都会以这样或那样的方式影响到模板缓冲。
glEnable(GL_STENCIL_TEST);
注意:在Android中,只使用这句是无法启用模板测试的,还需要使用下面代码配置GLSurfaceView,因为默认的配置是没有配置模板测试的。
要注意的是,像颜色和深度缓冲一样,在每次循环,你也得清空模板缓冲。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2、开启/禁止模板缓冲区写入
同时,和深度测试的glDepthMask
函数一样,模板缓冲也有一个相似函数。glStencilMask
允许我们给模板值设置一个位掩码(Bitmask,掩码是一种用于对数据进行编码和解码的技术,通过二进制代码对目标字段进行位与运算,屏蔽当前的输入位,从而实现数据的部分或全部隐藏,以保护敏感信息。掩码在计算机科学和数据处理中有着广泛的应用,包括数据压缩、权限控制、网络编程等,掩码在图像处理和对象分割等领域中用于标识和处理特定的图像区域。),它与模板值进行按位与(AND)运算决定缓冲是否可写。默认设置的位掩码都是1,这样就不会影响输出,但是如果我们设置为0x00,所有写入模板缓冲最后都是0。这和深度缓冲的glDepthMask(GL_FALSE)
很类似:
// 0xFF == 0b11111111
//此时,模板值与它进行按位与运算结果是模板值,模板缓冲可写
// 每一位写入模板缓冲时都保持原样
glStencilMask(0xFF); // 0x00 == 0b00000000 == 0
//此时,模板值与它进行按位与运算结果是0,模板缓冲不可写
// 每一位在写入模板缓冲时都会变成0(禁用写入)
//注意:他不是关闭模板,而是不让模板被写入,关闭模板的话连判断都没了。
glStencilMask(0x00);
大多数情况你的模板遮罩(stencil mask)写为0x00或0xFF就行,但是最好知道有一个选项可以自定义位遮罩。
3、模板测试策略函数
和深度测试类似,模板测试也有对应的api函数来设置模板测试的策略,如测试失败或者成功的情况下如何处理模板缓冲区。glStencilFunc函数决定一个片段的去留——是否会显示在屏幕上。通过测试则显示,否则不显示。
模板测试提供了两个函数:glStencilFunc and glStencilOp.
void glStencilFunc(GLenum func, GLint ref, GLuint mask)
函数有三个参数:
- func:设置模板测试操作。这个测试操作应用到已经储存的模板值和 giStenciFunc 的 ref 值上即判断模板测试func:通过的条件,例如我func设置为GL EQUAL,ref为1,那么模板测试通过的条件就是模板值等于1,可用的选项是:
GL_NEVER
、GL_LEQUAL
、GL_GREATER
、GL_GEQUAL
、GL_EQUAL
、GL_NOTEQUAL
、GL_ALWAYS
。它们的语义和深度缓冲的相似。func设置模板测试成功与否的策略。包括下面几种情况:
func策略 | 描述 |
---|---|
GL_NEVER | 每次模板测试都失败 |
GL_LESS | 比参考值更小就通过测试 |
GL_LEQUAL | 小余或等于参考值就通过测试 |
GL_GREATER | 比参考值更大就通过测试 |
GL_GEQUAL | 大于或等于参考值就通过测试 |
GL_EQUAL | 缓冲区的值和参数值ref相等 |
GL_NOTEQUAL | 缓冲区的值和参数值ref不相等 |
GL_ALWAYS | 每次模板测试都成功 |
- ref:指定模板测试的参考值,这个值会用来和模板缓冲区中的值进行比较,来判断是否丢弃片段(按照上述func参数设置的类型进行比较)。
- mask:设置一个掩码,在模板缓冲区和ref参考值进行比较值前,会使用mask做一个按位与的操作,初始化当前值,一般是在为0xFF即可,保留原值。
在上面简单模板的例子里,方程应该设置为:
glStencilFunc(GL_EQUAL, 1, 0xFF)
它会告诉OpenGL,无论何时,一个片段模板值等于(GL_EQUAL
)引用值1
,片段就能通过测试被绘制了,否则就会被丢弃。
但是glStencilFunc
只描述了OpenGL对模板缓冲做什么,而不是描述我们如何更新缓冲。这就需要glStencilOp
登场了。
4、更新模板缓冲
glStencilOp函数决定片段如何改变模板。判断达成某些条件的片段,要如何更新模板。这个函数决定一个片段,是否并如何改变一个模板上的值。
void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)
函数包含三个选项,我们可以指定每个选项的动作:
- sfail: 如果模板测试失败将采取的动作。
- dpfail: 如果模板测试通过,但是深度测试失败时采取的动作。
- dppass: 如果深度测试和模板测试都通过,将采取的动作。
每个选项都可以使用下列任何一个动作。
操作 | 描述 |
---|---|
GL_KEEP | 保持现有的模板值 |
GL_ZERO | 将模板值置为0 |
GL_REPLACE | 将模板值设置为用glStencilFunc 函数设置的ref值 |
GL_INCR | 如果模板值不是最大值就将模板值+1 |
GL_INCR_WRAP | 与GL_INCR 一样将模板值+1,如果模板值已经是最大值则设为0 |
GL_DECR | 如果模板值不是最小值就将模板值-1 |
GL_DECR_WRAP | 与GL_DECR 一样将模板值-1,如果模板值已经是最小值则设为最大值 |
GL_INVERT | 按位反转当前模板缓冲区的值 |
如设置:
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
则表示模板测试失败时,保持原有模板值,模板测试成功但是深度测试失败时保持原有模板值,两种都成功,则更新模板值为参考值。
glStencilOp
函数默认设置为 (GL_KEEP, GL_KEEP, GL_KEEP) ,所以任何测试的任何结果,模板缓冲都会保留它的值。默认行为不会更新模板缓冲,所以如果你想写入模板缓冲的话,你必须像任意选项指定至少一个不同的动作。
使用glStencilFunc
和glStencilOp
,我们就可以指定在什么时候以及我们打算怎么样去更新模板缓冲了,我们也可以指定何时让测试通过或不通过。什么时候片段会被抛弃。glStencilOp一般只设置一次,而glStencilFunc在绘制每个模型前都会设置一次。
5、模板测试应用——物体轮廓
下面我们使用一个案例来分析模板测试。
看了前面的部分你未必能理解模板测试是如何工作的,所以我们会展示一个用模板测试实现的一个特别的和有用的功能,叫做物体轮廓(Object Outlining)。
物体轮廓就像它的名字所描述的那样,它能够给每个(或一个)物体创建一个有颜色的边。在策略游戏中当你打算选择一个单位的时候它特别有用。给物体加上轮廓的步骤如下:
- 首先开启模板测试,清空模板缓冲区,开启模板缓冲区写入
- 在绘制源物体之前设置模板测试操作为GL_ALWAYS,设置参考值为1,掩码为0xFF,这样可以在每次绘制的时候都可以将模板缓冲区写入1。//使用gIStencil0p选项中的GL_REPLACE将模板值设置成glStencilFunc中的ref值
- 绘制源物体,写入模板缓冲
- 禁止模板缓冲区写入并禁止深度测试。
- 将源物体放大一点。
- 使用一个纯颜色的片段着色器对源物体进行绘制。
- 绘制源物体,但是此时使用GL_NOTEQUAL 的方式进行模板缓冲区绘制策略
- 重新开启深度缓冲区和模板可写入操作。
这个过程将每个物体的片段模板缓冲设置为1,当我们绘制边框的时候,我们基本上绘制的是放大版本的物体的通过测试的地方,放大的版本绘制后物体就会有一个边。我们基本会使用模板缓冲丢弃所有的不是原来物体的片段的放大的版本内容。
场景中的物体边框的绘制方法最后看起来像这样:
glEnable(GL_DEPTH_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);glStencilMask(0x00); // 绘制地板时确保关闭模板缓冲的写入
normalShader.Use();
DrawFloor() glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
DrawTwoContainers();glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
shaderSingleColor.Use();
DrawTwoScaledUpContainers();
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
理解这段代码后面的模板测试的思路并不难以理解。如果还不明白尝试再仔细阅读上面的部分,尝试理解每个函数的作用,现在你已经看到了它的使用方法的例子。
这个边框的算法的结果在深度测试教程的那个场景中,看起来像这样:
三、模板缓冲如何使用
使用模板缓存,分为两大部分:
1、创建模板缓冲
- 创建Stencil,用其他模型,遮罩等的片段,去创建模板缓冲。(遮罩也完全可以不被显示出来,只更新模板)
- 打开模板缓冲的写入 glStencilMask(0xFF) ,用某些模型,或遮罩图片,写入缓冲。
2、使用模板缓冲
利用创建好的Stencil去和需要被遮罩处理的片段比较,去决定目标片段是否被保留。
3、模板缓冲应用——描边
描边的例子步骤如下:
1、创建模板缓冲
打开模板缓冲的写入和深度测试,以正常的绘制模型和写入模板。
写入原始模型的片段(绘图),同时写入模板缓冲(创建Mask)
2、使用缓冲的部分
关闭模板缓冲写入,防止模板为污染
关闭Z-test深度测试,将描边画在最上面。
将原始模型放大一点,改用单色shader(描边色)
当模板值不是1的时候,写入单色(中间有原模型的部位,不会被写入。没有原模型的部位,被写入。)
注意整体绘制顺序,因为关闭ZBuffer深度缓冲之后,后画的一定会覆盖先画的。
四、源码下载
推荐文章
android opengl测试demo opengl模板测试_mob64ca14150f43的技术博客_51CTO博客
https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/02%20Stencil%20testing/#_1https://zhuanlan.zhihu.com/p/620697689
OpenGL学习笔记——StencilBuffer-腾讯游戏学堂
学习OpenGL ES for Android(十九)— 模板测试_gles20-CSDN博客
相关文章:

Android OpenGL ES详解——模板Stencil
目录 一、概念 1、模板测试 2、模板缓冲 二、模板测试如何使用 1、开启和关闭模板测试 2、开启/禁止模板缓冲区写入 3、模板测试策略函数 4、更新模板缓冲 5、模板测试应用——物体轮廓 三、模板缓冲如何使用 1、创建模板缓冲 2、使用模板缓冲 3、模板缓冲应用——…...

vscode在cmake config中不知道怎么选一个工具包?select a kit
vscode在cmake config中不知道怎么选一个工具包,或者发现一直在用VS的工具包想换成自己的工具包。select a kit vscode在cmake config中不知道怎么选一个工具包,或者发现一直在用VS的工具包想换成自己的工具包。select a kit 1.在VSCode中 按ctrlshift…...

无人机之无线电监测设备技术篇
一、技术原理 无人机的无线电监测设备主要通过捕捉和分析无人机发出的无线电信号来实现对无人机的监测和定位。这些信号包括无人机的上行遥控信号、下行数据图传信号等。设备采用多种技术手段,如频谱分析、信号解调、定位算法等,对接收到的信号进行处理和…...
【系统架构设计师】预测试卷一:案例分析
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 试题一(共25分)【问题 1】(12分)【问题 2】(13分)试题二(共 25分)【问题 1】(12分)【问题 2】(7分)【问题 3】(6分)试题三(共25分)【问题 1】(9分)【问题 2】(16分)试题四(共25分)【问题 1】…...

一篇文章教会你I2C通信(软件I2C和硬件I2C)以读取MPU6050为例,附STM32代码示例
目录 一、I2C通信介绍: (1)基本概念: (2)特点: (3)工作原理: 二、I2C通信原理: (1)I2C 物理层: &…...
Python实现SPFA算法
目录 Python实现SPFA算法引言一、SPFA算法的理论基础1.1 最短路径问题1.2 SPFA算法的基本原理1.3 SPFA算法的复杂度 二、SPFA算法的Python实现2.1 基本实现2.2 案例一:使用SPFA算法进行城市交通最短路径计算2.2.1 实现代码 2.3 案例二:负权重边的处理2.3…...

MYSQL安装(ubuntu系统)
rpm -qa 查询安装软件包 ps axj 查询服务 卸载mysql(万不得已) ps axj | grep mysql 查看是否存在mysql服务 systemctl stop mysqld 关闭该服务 rpm -qa | grep mysql 查安装mysql安装包 rmp -qa | grep mysql | xargs (yum apt) -y remove进行批量…...

Cpp二叉搜索树的讲解与实现(21)
文章目录 前言一、二叉搜索树的概念定义特点 二、二叉树的实现基本框架查找插入删除当只有0 ~ 1个孩子的时候当有2个孩子的时候 三、二叉树的应用K模型KV模型 四、二叉树的性能分析总结 前言 这是全新的一个篇章呢,二叉搜索树是我们接下来学习set、map的前提 迈过它…...

微服务设计模式 — 补偿事务模式(Compensating Transaction Pattern)
微服务设计模式 — 补偿事务模式(Compensating Transaction Pattern) 定义 在云计算和分布式系统中,管理跨多个微服务或组件的事务一致性是一项极具挑战性的任务,补偿事务模式Compensating Transaction Pattern)是一种…...

20 实战:形状编码、运动补偿和纹理编码的实现(基于python)
在当今多媒体时代,视频处理与编码已经成为各个领域中不可或缺的一部分。无论是视频编辑、流媒体传输,还是计算机视觉应用,视频编码技术都扮演着关键角色。本文将详细解析一个基于Python的图形用户界面(GUI)视频编码器。通过对代码的逐行讲解、功能分析以及参数调节方法的探…...

区块链-C++挖矿软件XMRIG源码分析
C++挖矿软件源码分析 3rdpartybackendgrgon2Obfusheader.hmain 程序 xmrig.cppxmrig命名空间process类Entry::IdApp类CoreControllerbasetoolkernelinterfacesDonateStrategy.cppdonate.h/2/dmiCmake 跨平台的自动化构建系统CMakeLists.txt.cmake 13个引入算力哈希率 HashrateE…...

C语言指针的介绍
零.导言 在日常生活中,我们常常在外出时居住酒店,细心的你一定能发现酒店不同的房间上有着不同的门牌号,上面写着像308,512之类的数字。当你定了酒店之后,你就会拿到一个写有门牌号的钥匙,凭着钥匙就能进入…...

八大排序算法——堆排序
目录 前言 一、向上调整算法建堆 二、向下调整算法建堆 三、堆排序 前言 堆排序是基于堆结构的一种排序思想,因此要为一个乱序的数组进行排序的前提是数组必须要是一个堆,所以要先对数组进行建堆操作 一、向上调整算法建堆 时间复杂度:O…...

U盘文件不翼而飞?这些数据恢复工具帮你找回!
U盘因其便携性是我们日常工作和生活中不可或缺的工具。不过有时候它也会出点小状况。如果你U盘里的数据突然不见了,不要着急,可以先试试这几款数据恢复工具! 福昕数据恢复 直达链接:www.pdf365.cn/foxit-restore/ 操作教程&…...
在Java中 try catch 会影响性能吗?
1、在Java中,异常处理确实会对性能产生影响,但在正常执行的代码路径中,即没有发生异常的情况下,try-catch块的性能影响是微不足道的 2、但是,如果出现异常被抛出时,Java虚拟机需要执行一些额外的操作来处理…...

吞吐量最高飙升20倍!破解强化学习训练部署难题
**强化学习(RL)对大模型复杂推理能力提升有关键作用,然而,RL 复杂的计算流程以及现有系统局限性,也给训练和部署带来了挑战。近日,字节跳动豆包大模型团队与香港大学联合提出 HybridFlow(开源项…...
redis的数据过期策略
Redis对数据设置了数据的有效时间,数据过期之后,就需要将数据从内存中删除掉.可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略),而这种策略有两种:惰性删除和定期删除 惰性删除:设置key过期时间后,我们不去管它,当需要该key时,我们在检查其是否…...

三周精通FastAPI:27 使用使用SQLModel操作SQL (关系型) 数据库
官网文档:https://fastapi.tiangolo.com/zh/tutorial/sql-databases/ SQL (关系型) 数据库 FastAPI不需要你使用SQL(关系型)数据库。 但是您可以使用任何您想要的关系型数据库。 这里我们将看到一个使用SQLModel的示例。 SQLModel是在SQLAlchemy和Pydantic的基础…...

Kubernetes金丝雀发布
华子目录 Canary金丝雀发布什么是金丝雀发布Canary发布方式基于header(http包头)灰度发布基于权重的金丝雀发布 Canary金丝雀发布 什么是金丝雀发布 金丝雀发布也称为灰度发布,是一种软件发布策略主要目的是在将新版本的软件全面推广到生产环…...
树形DP讲解
文章目录 树形DP讲解一、引言二、树形DP基础1、树的定义2、树形DP的基本思想3、代码示例:子树大小 三、经典例题解析1、树的平衡点1.1、代码示例 2、没有上司的舞会(树的最大独立集)2.1、代码示例 四、总结 树形DP讲解 一、引言 树形动态规…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...