为什么我能够在 Linux 内核模块内执行浮点运算?

2024-10-21 09:14:00
admin
原创
420
摘要:问题描述:我在 x86 CentOS 6.3(内核 v2.6.32)系统上运行。我将下面的函数编译成一个简单的字符驱动模块,作为实验来查看 Linux 内核对浮点运算的反应。static unsigned floatstuff(void){ float x = 3.14; x *= 2.5; ...

问题描述:

我在 x86 CentOS 6.3(内核 v2.6.32)系统上运行。

我将下面的函数编译成一个简单的字符驱动模块,作为实验来查看 Linux 内核对浮点运算的反应。

static unsigned floatstuff(void){
    float x = 3.14;
    x *= 2.5;
    return x;
}

...

printk(KERN_INFO "x: %u", x);

代码编译成功(这是意料之外的),因此我插入模块并用 检查了日志dmesg。日志显示:x: 7

这看起来很奇怪;我以为你不能在 Linux 内核中执行浮点运算——除了一些例外,例如kernel_fpu_begin()。模块如何执行浮点运算?

这是因为我使用的是 x86 处理器吗?


解决方案 1:

我以为你不能在 Linux 内核中执行浮点运算

您不能安全地:使用kernel_fpu_begin()/失败kernel_fpu_end()并不意味着 FPU 指令会出现故障(至少在 x86 上不会)。

相反,它会悄悄破坏用户空间的 FPU 状态。这很糟糕;不要这样做。

编译器不知道这是什么kernel_fpu_begin()意思,所以它无法检查/警告在 FPU 开始区域之外编译为 FPU 指令的代码。

可能存在一种调试模式,其中内核确实禁用kernel_fpu_begin/end区域之外的 SSE、x87 和 MMX 指令,但这会比较慢并且默认情况下不会执行。

但这是可能的:设置CR0::TS = 1会导致 x87 指令出错,因此延迟的 FPU 上下文切换是可能的,并且还有其他用于 SSE 和 AVX 的位。


内核代码存在许多缺陷,可能导致严重问题。这只是众多问题之一。在 C 语言中,您几乎总是知道何时使用浮点数(除非拼写错误导致常量1.或实际编译上下文中的某些内容)。


为什么FP架构状态与整数不同?

jmpLinux 每次进入/退出内核时都必须保存/恢复整数状态。所有代码都需要使用整数寄存器(除了以而不是retret修改)结尾的 FPU 计算的巨大直线块rsp)。

但是内核代码通常会避免使用 FPU,因此 Linux 在系统调用进入时不会保存 FPU 状态,仅在实际上下文切换到不同的用户空间进程或之前保存kernel_fpu_begin。否则,通常会返回到同一核心上的同一用户空间进程,因此不需要恢复 FPU 状态,因为内核没有触及它。(如果内核任务确实修改了 FPU 状态,就会发生损坏。我认为这是双向的:用户空间也可能破坏您的FPU 状态)。

整数状态相当小,只有 16x 64 位寄存器 + RFLAGS 和段寄存器。即使没有 AVX,FPU 状态也是两倍多:8x 80 位 x87 寄存器,16x XMM 或 YMM,或 32x ZMM 寄存器(+ MXCSR,以及 x87 状态 + 控制字)。此外,MPXbnd0-4寄存器与“FPU”合并在一起。此时,“FPU 状态”仅表示所有非整数寄存器。在我的 Skylake 上,dmesg显示x86/fpu: Enabled xstate features 0x1f, context size is 960 bytes, using 'compacted' format.

请参阅了解 Linux 内核中的 FPU 使用情况;现代 Linux 默认不会对上下文切换执行惰性 FPU 上下文切换(仅对内核/用户转换执行惰性 FPU 上下文切换)。(但那篇文章解释了什么是惰性。)

大多数进程使用 SSE 来复制/清零编译器生成的代码中的小块内存,并且大多数库字符串/memcpy/memset 实现都使用 SSE/SSE2。此外,硬件支持的优化保存/恢复现在已成为现实(xsaveopt/xrstor),因此如果某些/所有 FP 寄存器实际上没有被使用,“急切的”FPU 保存/恢复实际上可能做的工作更少。例如,如果 YMM 寄存器的低 128b 被清零,则仅保存它们,vzeroupper以便 CPU 知道它们是干净的。(并在保存格式中仅用一位标记该事实。)

通过“急切”的上下文切换,FPU 指令始终保持启用状态,因此错误的内核代码可能随时破坏它们。

解决方案 2:

不要这样做!

在内核空间中,FPU 模式由于以下几个原因而被禁用:

  • 它允许 Linux 在没有 FPU 的架构中运行

  • 它避免在每次内核/用户空间转换时保存和恢复整个寄存器集(它可能会使上下文切换的时间加倍)

  • 基本上所有的内核函数都使用整数来表示十进制数 - >你可能不需要浮点数

  • 在 Linux 中,当内核空间以 FPU 模式运行时,抢占被禁用

  • 浮点数是邪恶的,可能会产生非常糟糕的意外行为

如果您确实想使用 FP 数字(而您不应该这样做),那么您必须使用kernel_fpu_beginkernel_fpu_end原语来避免破坏用户空间寄存器,并且您应该考虑处理 FP 数字时可能出现的所有问题(包括安全性)。

解决方案 3:

不确定这种看法从何而来。但内核与用户模式代码在同一个处理器上执行,因此可以访问相同的指令集。如果处理器可以执行浮点运算(直接或通过协处理器),那么内核也可以。

也许你正在考虑在软件中模拟浮点运算的情况。但即便如此,它仍可在内核中使用(除非以某种方式禁用)。

我很好奇,这种看法从何而来?也许我忽略了什么。

找到了这个。似乎是一个很好的解释。

解决方案 4:

操作系统内核可能只是在内核模式下关闭 FPU。

当FPU运行时,浮点运算时内核会打开FPU,然后关闭FPU。

但你不能打印它。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2588  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1553  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   31  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   26  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   21  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用