LWN:把atomic kmap改成local kmap!

ext2文件系统源代码之dir.c 今天我们来看ext2源代码的dir.c文件,这个文件是做和目录有关的操作的,也是很重要的一个文件,大家认真看哦,有什么和我不一致的大家一起探讨~~ 在讲这个之前我觉得还是先说下ext2文件系统的目录方面的基础比较好,这样会更容易看明白。 ext2文件系统分为inode和block,inode是索引,block是数据块,那我们怎么定义目录呢?其实,目录其实也是文件的一种,只不过是目录的内容是目录 阅读详情

关注了就能看到更多这么棒的文章哦~

Atomic kmaps become local

By Jonathan Corbet
November 6, 2020
DeepL assisted translation
https://lwn.net/Articles/836144/

内核中的 kmap()接口在某种意义上是个挺奇怪的 API,它的存在意义,完全只是用来克服 32 位 CPU 的虚拟寻址限制的,但是它影响了整个内核中各处的代码,而且对 64 位机器还有副作用。。最近一次关于内核内部的 preemption(抢占)的处理的讨论中,暴露出来一些需要注意的问题,其中之一就是 kmap()API。现在,人们提出了一个名为 kmap_local() 的 API ,对其进行扩展,从而解决其中的一些问题。它标志着内核社区在把 32 位机器从优先支持等级移除出去的过程又走出了一步。

Why we have kmap()

32 位处理器当然都会使用 32 位的指针,这就限制了内存的寻址空间在 4GB 之内。这 4GB 地址空间被分给用户空间(user space)和内核(kernel)。在最常见的分配方式中,内核分到了 1GB,这个空间内存放着内核的代码和数据、memory-mapped I/O 区域,以及让内核访问物理内存的 "direct map"。这个 direct map 肯定不能覆盖太多的内存,为了照顾到内核的其他需求,那么这里能映射到的物理内存就只能是远远少于 1GB 了。

因此,任何拥有 1GB 以上物理内存的系统,其部分内存都是没有在 direct map 中映射的,需要其他方式来管理。位于可以 direct map 的范围之上的内存称为 "high memory";在很多系统中,大部分内存空间都是 high memory。用户空间可以直接使用 high memory,不会感到任何区别,但内核方面就比较复杂了。每当内核必须访问一个位于 high memory 的 page 时(例如,在把一个 page 交给用户空间之前要把它清零),它必须首先为这个页面创建一个临时映射。kmap()接口就是用来管理这些映射的。

kmap()函数本身,会将一个 page 映射到内核的地址空间,然后返回一个指针,接下来就可以用这个指针来访问 page 的内容了。不过,用这种方式创建的映射开销是很大的。它们会占用地址空间,而且关于这个映射关系的改动必须要传播给系统的所有 CPU,这个操作开销很大。如果一个映射需要持续使用比较长的时间,那么这项工作是必要的,但是内核中的大部分 high memory 映射都是短暂存在的,并且只在一个地方来使用。这种情况下,kmap()的开销中大部分都被浪费了。

因此,人们加入了 kmap_atomic()API 作为避免这种开销的方法。它也能做到将一个 high memory 的 page 映射到内核的地址空间中,但是有一些不同。它会从若干个 address slot 中挑一个进行映射,而且这个映射只在创建它的 CPU 上有效。这种设计意味着持有这种映射的代码必须在原子上下文中运行(因此叫 kmap_atomic())。如果这部分代码休眠了,或被移到另一个 CPU 上,就肯定会出现混乱或者数据损坏了。因此,只要某一段在内核空间中运行的代码创建了一个 atomic mapping,它就不能再被抢占或迁移,也不允许睡眠,直到所有的 atomic mapping 被释放。

在 64 位系统上,调用 kmap()和 kmap_atomic() 的话实际上不需要做上面这些改变映射的动作了。64 位的地址空间足以涵盖人们在真实世界中任何系统上安装的内存了(或者说是目前足够了),所以所有的物理内存都出现在 direct map 中。但是调用 kmap_atomic()的话,无论如何都会禁用抢占,这主要是作为一种调试手段:确保在保持 atomic mapping 时发生睡眠的代码会在 64 位系统上产生错误,这意味着这种 bug 更容易在真正在 32 位系统上导致大问题之前被报出来,尤其是 32 位的系统现在很多开发人员测试不到了。

禁用抢占对于实时开发者来说是一个显眼的警告信号,他们多年来一直努力确保在任何时候所有 CPU 都可以被更高优先级的任务抢占进来。内核中成百上千的 kmap_atomic()调用点,每个都会产生一小段不可抢占的部分,这可能会导致不必要的延迟。上次提出这个话题的时候,曾有过一个简短的讨论,即希望从内核中完全取消对 high memory 的支持。此举会简化很多代码,肯定会很受欢迎,但也会破坏对现有系统的支持,如果这些系统仍会使用新的内核的话。所以,high memory 支持目前还不能完全从内核中移除。

Shifting the cost

因此,开发者不得不为这个问题找到一个次优的解决方案;这个解决方案很可能是 Thomas Gleixner 的 kmap_local() patch set。它提供了一组类似 kmap_atomic() 的新函数,但不需要禁用抢占。新函数是

void *kmap_local_page(struct page *page);
void *kmap_local_page_prot(struct page *page, pgprot_t prot);
void *kmap_local_pfn(unsigned long pfn);
void kunmap_local(void *addr);

前两个函数的输入参数就是一个指向与目标 page 所对应的 struct page 的指针,并会返回 page 映射上来之后的地址。第二个函数还额外允许调用者指定对这个映射上来的 page 要采用什么保护方式。如果调用者有一个 page-frame number,没有 struct page,那么可以使用 kmap_local_pfn()。无论 mapping 是用什么 API 如何创建的,都要用 kunmap_local()销毁。

这些 mapping 内部与用 kmap_atomic() 实现相同。但这个 patch set 对 kmap_atomic()的实现方式进行了重大修改。在当前的内核中,每个架构都有自己的实现,但几乎所有的代码都是一样的。Gleixner 清理了这种重复撰写的代码,并将这些统一成一个单一的、跨架构的实现。因此,这个 patch set 在增加新功能的时候,删除了 600 多行代码。

在这个公用实现完成之后,用于管理这些短期映射的 slot 的就会发生变化。在当前的内核中,这些 slot 被存储在一个 per-CPU 数据结构中,因此它们会被运行在同一个 CPU 上的所有线程共享。这也是为什么在持有 atomic mapping 时不能允许抢占的原因之一。正在运行的进程和抢占它的进程可能都会试图使用相同的 slot,结果一般都会导致出现各种错误了。在新的方案中,mapping 被存储在 task_struct 结构中,因此它们对每个线程来说是唯一的。

不过,(在 32 位系统上)用来做 mapping 的那个 page-table entry 可不能是 per-thread,所以在这种情况下必须做更多的动作才能安全地启用抢占。在上下文切换时,新的代码会查看退出或进入的这个 task 是否有仍然有效的 local mapping。如果有的话,退出的任务的 mapping 就会被移除掉,而进入的任务的映射则会被重新建立起来。这个动作会让上下文切换的速度变慢一些,但是,正如 Gleixner 所指出的那样:"显然这里会慢,但无论如何,访问 high memory 都是慢的".

local page mapping 仍然只会在 local CPU 上被建立起来,这意味着持有这种映射的进程如果要做迁移的话肯定是自找麻烦。因此,虽然当内核代码建立 local mapping 时抢占仍然是允许的,但从一个 CPU 到另一个 CPU 的迁移动作是被禁止的。值得注意的是,当前的内核并没有这样禁用迁移的机制,迄今为止这个功能仅限于 realtime kernel。Peter Zijlstra 一直在为一般情况下的迁移禁用实现添加支持,但尚未合并。这显然是 kmap_local()能够用起来的先决条件。

一旦一切就绪之后,kmap_atomic()和 kmap_local()之间唯一的区别将是持有 mapping 时的执行上下文了。atomic mapping 仍然禁用抢占,而 local mapping 只禁用迁移。除此以外,这两种 mapping 效果是相同的。这就引出了一个显而易见的问题:为什么不直接把所有地方都换成 kmap_local()呢?这的确是长期目标,但有一个小问题:一些 kmap_atomic()的调用点非常依赖于必须要关闭抢占,甚至也许开发者甚至没有意识到这一点。因此,数百个调用位置中的每一个都需要逐一进行核对和转换。

这项工作预计需要一段时间,但最终会有一天,kmap_atomic()不再被使用,从而可以从内核中移除。新的 API 保留了 32 位系统的功能,但它将部分成本转移到了这类系统上,而不是现在占主导地位的 64 位系统。这并不是取消对 high memory 的支持,而是表明使用 high memory 的系统越来越被视为一种小众场景,不会永远都能得到支持了。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

NVIDIA驱动版本太低?手把手教你解决CUDA与PyTorch版本冲突问题 本文针对深度学习开发中常见的NVIDIA驱动版本过低导致的CUDA与PyTorch版本冲突问题,提供了从根源理解到实战解决的完整指南。文章详细解析了驱动、CUDA与PyTorch的依赖关系,并给出了升级驱动、降级PyTorch、使用Conda环境管理及Docker容器化四种核心解决方案,帮助开发者快速诊断并构建稳定的GPU开发工作流。 阅读详情

相关推荐

CyberChef本地搭建

CyberChef本地搭建

2301_80241182的博客 6071

突破32位限制:Linux内核高端内存与PAE技术深度解析

你是否曾疑惑:32位Linux系统为何能支持超过4GB的物理内存?当服务器需要处理海量数据时,传统内存管理如何突破地址空间瓶颈?本文将详解Linux内核如何通过高端内存(High Memory)机制与物理地址扩展(Physical Address Extension, PAE)技术,让32位系统焕发新生。读完本文,你将掌握: - 32位系统内存限制的底层原因 - 高端内存的分区策略与临时映射机制...

gitblog_00687的博客 515

LQR控制算法调参指南:如何通过Bryson‘s Rule和Trial-and-Error优化自动驾驶性能?

本文深入探讨了LQR控制算法在自动驾驶系统中的调参策略,从Bryson's Rule的基础应用到工程落地的优化方法。通过动态权重适应、非对角项引入和多目标权衡等技巧,提升车辆轨迹跟踪精度与操控舒适性。文章还介绍了数据驱动的调参流程和典型问题的解决方案,为自动驾驶工程师提供实用指南。

kkk56的博客 1024

Atomic、ThreadLocal、Volatile、synchronized总结

Atomic、ThreadLocal、Volatile、synchronized总结 多线程安全: 三个独立的功能——原子性、可见性和顺序性Atomic: 原子操作: 它会在这步操作都完成情况下才允许其它线程再对它进行操作,这个实现是通过Lock-Free原子操作指令来确定的 Atomic原子操作类,Java的concurrent并发包中几个常用原子操作类AtomicInteger、Ato

keen_zuxwang的博客 847

ESP32-IDF HTTP服务器实战:从零搭建Web控制界面

本文详细介绍了如何在ESP32平台上使用ESP-IDF框架从零搭建HTTP服务器,并创建Web控制界面。内容涵盖环境配置、服务器基础设置、Web页面处理、GPIO控制接口实现及AJAX异步请求处理,帮助开发者快速掌握物联网设备Web控制开发。

efc123456的博客 1063

Ubuntu22.04下,用Fast-LIVO2+3DGS重建桌面小物件:从点云到高清模型的保姆级避坑实录

本文详细介绍了在Ubuntu22.04环境下,使用Fast-LIVO2与3DGS技术进行桌面小物件三维重建的完整流程。从环境配置、数据采集到点云-图像对齐和3DGS训练,提供了针对小物件优化的参数设置和避坑指南,帮助用户实现媲美商业扫描仪的高清模型重建效果。

weixin_30897233的博客 398

linux内存管理:kmap、vmap、ioremap

目录 散列表也是哈希表 kmap实现 page_address_map pkmap_count page_address_slot 哈希函数 kmap函数实现 kmap_init kmap kmap_high page_address map_new_virtual set_page_address kunmap kunmap_high(struct page *page)函数实现 vmap实现 vmap函数 vunmap函数 ioremap ioremap函数 _

RToax 8926

终于搞定!Cloudflare Tunnel 报错 Error 1033,一次完整修复记录

最近遇到了 Cloudflare Tunnel Error 1033 报错的问题,本文记录了完整的排查和解决方案💡

XiaoqiangClub的博客 1751

内核 kmap_atomic分析

主要谈三个问题。 1、为什么会有这个函数? 我想主要的原因就是kmap_atomic在效率上要比kmap提升不少。 在kmap函数中,会有如下几个比较耗时的部分: 1)、page_address函数 2)、Sleep for somebody else to unmap their entries 代码如下: 171 ____________DECLARE_WAITQUEUE(wait, current); 173 ______________set_current_state(TASK_UNINTERRU

runshui27的博客 582

5、模糊风险评估

本文介绍了基于模糊逻辑的风险评估方法,探讨了如何在不确定、不完整信息环境下进行高效的风险分析。文章涵盖了模糊集合与隶属度函数的基本概念、模糊推理系统的流程,并结合犯罪风险、金融风险和医疗诊断等实际案例,展示了模糊风险评估的应用价值和技术细节。此外,还介绍了模糊贝叶斯网络、模糊综合评价等进阶工具与方法,为多领域风险管理提供了理论支持和实践指导。

mango的博客 179

为什么我的 Spark Executor / Yarn Container 只有一个vCore?

在很多集群里,在关闭了Spark的DynamicAllocation的前提下(避免自动申请空闲资源,干扰测试结果),都会观察到:提交Spark作业时,申请 1 个 driver + n 个 executor 会在Yarn上会对应创建 n+1 个 container,但是每个container只有一个vCore,通过--driver-cores和--executor-cores设定的vCore数都未奏效。有人会因此错误的认为Yarn上的一个vCore对应一个Spark的executor,这是非常错误的,正确的

Laurence的技术博客 916

LWN:避免对持久性内存的误写入!

关注了就能看到更多这么棒的文章哦~Stray-write protection for persistent memoryBy Jonathan CorbetFebruary 3, 202...

Linux News搬运工 405

【RBF预测】基于粒子群算法优化RBF神经网络实现数据回归预测含Matlab源码

1 简介 原油含水率预测对于确定油井水,油层位以及估计原油产量有着非常重要意义.BP神经网络是最近常用的原油含水率预测方法,然而,由于BP神经网络存在容易陷入局部极小值,收敛速度慢等问题,影响了其预测的实用性和准确性,对此,提出基于粒子群优化RBF神经网络(PSO-RBFNN)的原油含水率预测方法,粒子群优化算法用于RBF神经网络参数优化.在分析原油含水率预测的影响因素基础上,建立粒子群优化RBF神经网络的原油含水率预测模型.实验结果表明,在原油含水率预测中,基于粒子群优化RBF神经网络比BP神经网络有着

qq_59747472的博客 1232

高端内存映射之kmap_atomic固定映射--Linux内存管理(二十一)

日期 内核版本 架构 作者 GitHub 优快云 2016-09-29 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法.Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算

OSKernelLAB(gatieme) 6427

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Linux kmap和kmap_atomic解析

名为解析,名不符实,简单记录一下。 kmap函数将分配到的高端内存映射到永久内存映射区域.。 kmap函数不能用于中断处理程序, 因为它可能进入睡眠状态。 上面内容引用自https://blog.youkuaiyun.com/gatieme/article/details/52705178 kmap_atomic用于高端内存映射,用于紧急的,短时间的映射,它没有使用任何锁,完全靠一个数学公式来避免...

zhanghaiyang9999的专栏 4886

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

深入理解Linux 内核 内存管理(上)

RAM中,剩下的自由部分被称为动态内存!因为这不仅是内进程所需要的宝贵资源,也是内核执行本身所需要的宝贵资源!实际上整个系统的性能都高度取决于如何有效的管理动态内存!因此内存管理是操作系统中非常重要的话题之一!

charlie114514191的博客 1317

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Linux设备驱动程序学习(21)-内存映射和DMA-数据结构

原文地址:Linux设备驱动程序学习(21)-内存映射和DMA-数据结构 作者:tekkamanninja     前面学习了内核内存管理的基本概念,现在再来看看内核用怎样的数据结构来管理这些物理内存和映射。     内核源码:Linux-3.0 一、物理页在内存中的数据结构及内存映射     由于历史原因, 内核使用逻辑地址来引用物理内存页。 但后来增加了对高内存的支

tigerly的专栏 1435

Linux操作系统之内存管理

文章目录内存管理进程空间管理物理内存管理用户态内存映射内核态内存映射 内存管理 操作系统的内存管理,主要分为三个方面 第一,物理内存的管理,相当于会议室管理员管理会议室。 第二,虚拟地址的管理,也即在项目组的视角,会议室的虚拟地址应该如何组织。 第三,虚拟地址和物理地址如何映射,也即会议室管理员如果管理映射表。 查看进程内存空间的布局的命令:cat /proc/进程id/maps 分段机制的原理 分段机制下的虚拟地址由两部分组成,段选择子和段内偏移量。段选择子就保存在咱们前面讲过的段寄存器里面

Carroll的博客 1001

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 225

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 149

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 330

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 195

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 117

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 365

Decorator

TaskDecorator 是异步场景下"跨线程传递上下文"的标准方案,主要用于传递 MDC、用户信息、数据源路由等上下文数据,核心价值是让异步任务的日志链路不中断、业务上下文不丢失。TaskDecorator 是 Spring 提供的一个钩子接口,用于在异步任务执行前对 Runnable 进行包装,常用于跨线程传递上下文。如果你在项目中遇到具体的异步上下文传递问题,可以把代码贴出来,我帮你给出最合适的 Decorator 方案 👍。✅ 核心能力:在线程切换时,把"父线程的上下文"搬到"子线程"

wlwork66的博客 104

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 626
上一篇: LWN:Android上使用KVM!
下一篇: LWN:抛弃不安全的scp命令!
LinuxNews搬运工
博客等级 码龄7年 438粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值