有些人出于某种原因想将代码从用户空间移动到 Linux 内核空间。很多时候,原因似乎是代码应该具有特别高的优先级,或者只是“内核空间更快”。
这对我来说似乎很奇怪。我什么时候应该考虑编写内核模块?有没有一套标准?
我如何激励将代码保留在(我相信)属于那里的用户空间中?
经验法则:尽最大努力将代码保留在用户空间中。如果您认为自己做不到,请花尽可能多的时间来研究内核代码的替代方案,就像编写代码一样(即:很长时间),然后再次尝试在用户空间中实现它。如果您仍然不能,请进行更多研究以确保您做出正确的选择,然后非常谨慎地进入内核。正如其他人所说,很少有情况要求编写内核模块和调试内核代码可能会非常糟糕,因此不惜一切代价避开。
至于在考虑编写内核模式代码时应该检查的具体条件,这里有一些: 它是否需要访问极低级别的资源,例如中断?您的代码是否为无法在当前导出的功能之上构建的硬件定义了新的接口/驱动程序?您的代码是否需要访问未从内核空间导出的数据结构或原语?您是否正在编写主要由其他内核子系统使用的东西,例如调度程序或 VM 系统(即使在这里,子系统也不一定是内核模式:Mach 对用户模式虚拟内存分页器有很强的支持,所以肯定可以做到)?
将东西放入内核的理由非常有限。如果您正在编写设备驱动程序,那没关系。任何标准应用程序:从不。
缺点是巨大的。调试变得更加困难,错误变得更加频繁且难以发现。您可能会损害安全性和稳定性。您可能必须更频繁地适应内核更改。移植到其他 UNIX 操作系统变得不可能。
我最接近内核的是自定义文件系统(在后台使用 mysql),甚至为此我们使用了 FUSE(其中 U 代表用户空间)。
我不确定这个问题是否正确。将事物移至内核空间应该有充分的理由。如果没有任何理由,请不要这样做。
一方面,调试变得更加困难,并且错误的影响更糟(崩溃/恐慌而不是简单的核心转储)。
基本上,我同意 rpj。除非真的有必要,否则代码必须在用户空间中。
但是,为了强调你的问题,哪个条件?
有些人声称驱动程序必须在内核中,这是不正确的。有些司机对时间不敏感,事实上很多司机都是这样的。
例如,成帧器、RTC 定时器、i2c 设备等。这些驱动程序可以很容易地移动到用户空间。甚至有一些文件系统是在用户空间中编写的。
您应该转移到开销较大的内核空间,例如。用户内核交换,对于您的代码正常工作变得不可接受。
但是有很多方法可以解决这个问题。例如,/dev/mem 提供了一种访问物理内存的好方法,就像您从内核空间进行访问一样。
当人们谈论使用 RTOS 时,我通常持怀疑态度。这些天来,处理器是如此强大,以至于大多数时候,实时方面变得可以忽略不计。
但是,即使,假设您正在处理 SONET,并且您需要在 50 毫秒内进行保护切换(实际上甚至更少,因为 50 毫秒的约束适用于整个环),您仍然可以非常快速地进行切换,如果您硬件支持它。
如今,许多成帧器可以为您提供硬件支持,从而减少您需要执行的写入量。您的工作基本上是尽快响应中断。Linux 一点也不差。即使我有大量其他中断正在运行(例如 IDE、以太网等),我得到的中断延迟也少于 1 毫秒。
如果这还不够,那么您的硬件设计可能是错误的。有些东西最好留在硬件上。当我说硬件时,我指的是 ASIC、FPGA、网络处理器或其他高级逻辑。
在内核中运行的代码以不同于用户空间代码的方式访问内存、外围设备、系统功能,因此具有更高效率的能力。更不用说减少内核代码的安全限制了。然而,所有这一切通常都是有代价的,例如增加内核面临安全威胁的可能性、锁定操作系统、使调试复杂化等等。
如果您的员工想要真正的高优先级、确定性、低延迟等,那么正确的方法是使用一些实时版本的 Linux(或其他操作系统)。
还要查看可抢占的内核选项等。您应该做什么取决于要求,但是将代码放在内核模块中不太可能是正确的解决方案,除非您直接连接某些硬件。
不将代码移动到内核空间的另一个原因是,当您在生产或商业环境中使用它时,由于 GPL 协议,您必须发布该代码。许多软件公司都不想遇到这种情况。:)
作为一般规则。想想你想知道什么,如果这是你会在操作系统开发书籍或课程中看到的东西,那么它很有可能属于内核。如果没有,请将其排除在内核之外。如果您有充分的理由打破该规则,请确保您将拥有足够的知识来自己了解它,或者您将与具有该知识的人一起工作。
是的,听起来可能很刺耳,但这正是我的意思,如果你不知道,那么几乎可以肯定答案是否定的,不要在内核中这样做。将您的开发转移到内核空间会打开一大堆蠕虫,您必须确保能够处理这些蠕虫。
如果您只需要更低的延迟、更高的吞吐量等,那么购买速度更快的计算机可能比开发内核代码更便宜。
内核模块可能更快(由于更少的上下文切换、更少的系统调用开销和更少的中断),并且确实以非常高的优先级运行。如果您想将少量相当简单的代码导出到内核空间,这可能没问题。也就是说,如果发现一小段代码对性能至关重要,并且是可以从放置在内核模式中受益的那种代码,那么将其放置在那里可能是合理的。
但是应该避免将程序的大部分移动到内核空间,除非所有其他选项都完全用尽。除了这样做的难度之外,性能收益不太可能很大。
如果你问这样的问题,那么你不应该去内核层。基本上只是想知道意味着你不需要。上下文切换的时间是如此微不足道,以至于这些天无论如何都无关紧要。