在Linux内核中使用浮点


83

我正在阅读Robert Love的“ Linux内核开发”,并且遇到了以下段落:

无需(轻松)使用浮点数

当用户空间进程使用浮点指令时,内核将管理从整数到浮点模式的转换。内核在使用浮点指令时必须执行的操作因体系结构而异,但是内核通常会捕获陷阱,然后启动从整数模式到浮点模式的转换。

与用户空间不同,内核没有对浮点的无缝支持的奢侈之处,因为它无法轻易地陷入陷阱。在内核内部使用浮点数需要手动保存和恢复浮点数寄存器,以及其他可能的琐事。简短的答案是:不要这样做!除了极少数情况,内核中没有浮点运算。

我从未听说过这些“整数”和“浮点”模式。它们到底是什么?为什么需要它们?这种区别是否存在于主流硬件体系结构(例如x86)上,还是特定于某些更特殊的环境?从进程和内核的角度来看,从整数模式到浮点模式的转换到底需要什么?



2
这本书通过谈论“模式”使这个问题有些混乱。整数指令始终可用,但是FPU可以全部或部分禁用。没有有用的功能完全由FP ops组成,例如,所有控制指令都被视为“整数”。有关更多信息,请参见下文。
DigitalRoss

@DigitalRoss:我同意该术语。感谢您的回答顺便说一句,它使事情变得清晰起来。
NPE 2012年

知道在内核中进行浮点运算的期望是很有趣的。在试图在内核中做一些应在内核之外完成的事情时,说“糟糕的设计”是很诱人的,但是在利用FPU成为一种创新解决方案的情况下,也许内核确实应该做一些事情?
克里斯·斯特拉顿

2
由于没有人提及它,因此,如果您在内核内部使用FP(或SIMD),则需要在代码之前/之后调用kernel_fpu_begin()/kernel_fpu_end()以确保用户空间FPU状态没有损坏。这就是Linuxmd针对RAID5 / RAID6的代码。
彼得·科德斯

Answers:


86

因为...

  • 许多程序不使用浮点数,或在任何给定的时间段不使用浮点数;
  • 保存FPU寄存器和其他FPU状态需要花费时间;因此

...一个OS内核可能只是关闭了FPU。Presto,无状态可保存和恢复,因此上下文切换速度更快。(这就是该模式的含义,仅表示已启用FPU。)

如果程序尝试使用FPU op,则该程序将陷入内核,内核将打开FPU,还原可能已经存在的所有保存状态,然后返回以重新执行FPU op。

在上下文切换时,它知道实际上要经过状态保存逻辑。(然后它可能会再次关闭FPU。)

顺便说一句,我相信本书对内核(而不仅仅是Linux)避免FPU操作的解释并不十分准确。1个

内核可以陷入自身,并在很多方面做到这一点。(计时器,页面错误,设备中断等)。真正的原因是内核特别不需要FPU操作,并且还需要在完全没有FPU的体系结构上运行。因此,它通过不执行总是有其他软件解决方案的操作,从而避免了管理自己的FPU上下文所需的复杂性和运行时间。

有趣的是,如果内核要使用FP,则必须多久保存一次FPU状态。。。每个系统调用,每个中断,内核线程之间的每个切换。即使偶尔需要内核FP,2在软件中执行它可能也会更快。


1.那是完全错误的。
2.在某些情况下,我知道内核软件在哪里包含浮点算术实现。 一些体系结构在硬件中实现传统的FPU操作,但将一些复杂的IEEE FP操作留给软件。(认为​​:反常算术。) 当发生某些奇怪的IEEE极端情况时,它们会陷入软件中,该软件包含对可能陷入困境的操作进行正确的模拟。


16

对于某些内核设计,当“内核”或“系统”任务被任务切换出时,不会保存浮点寄存器。(这是因为FP寄存器很大,并且需要花费时间和空间来保存。)因此,如果您尝试使用FP,则这些值将随机变为“伪”。

另外,一些硬件浮点方案依靠内核通过陷阱来处理“奇数”情况(例如零除),并且所需的陷阱机制可能处于比当前内核任务正在运行的更高的“级别”。

由于这些原因(以及其他一些原因),当您在任务中首次使用FP指令时,某些硬件FP方案将被捕获。如果您被允许使用FP,则在任务中打开浮点标志,否则,射击队将您射击。


在Linux中,在代码之前/之后使用kernel_fpu_begin()/kernel_fpu_end()来触发用户空间FPU状态的保存/恢复(我猜您的内核FPU状态是针对抢占的)。
彼得·科德斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.