自己尝试实现C字符串库的时候,发现glibc和Linux内核实现一些功能的方式不同。例如,glibc memchr和glibc strchr使用一些技巧来加速函数,但内核 memchr和内核 strchr没有。为什么 Linux 内核函数不像 glibc 那样优化?
自己尝试实现C字符串库的时候,发现glibc和Linux内核实现一些功能的方式不同。例如,glibc memchr和glibc strchr使用一些技巧来加速函数,但内核 memchr和内核 strchr没有。为什么 Linux 内核函数不像 glibc 那样优化?
内核在特定于架构的目录中确实具有其中一些功能的优化版本;例如,参见 x86 实现
memchr
(参见所有memchr
定义和所有strchr
定义)。您找到的版本是后备通用版本;你可以通过寻找保护检查来发现这些,#ifndef __HAVE_ARCH_MEMCHR
formemchr
和#ifndef __HAVE_ARCH_STRCHR
forstrchr
。C 库的优化版本确实倾向于使用更复杂的代码,所以上面并没有解释为什么内核不竭尽全力加快速度。如果您能找到内核将从这些功能之一的更优化版本中受益的场景,我想一个补丁会受到欢迎(有适当的支持证据,并且只要优化的功能仍然可以理解 - 请参阅关于
memcpy
)。但是我怀疑内核对这些函数的使用通常不会让它变得值得。例如memcpy
,相关函数往往用于内核中的小缓冲区。并且永远不要低估适合缓存或可以内联的短函数的速度增益......此外,正如Iwillnotexist Idonotexist所提到的,MMX 和 SSE 不能轻易地在内核中使用,许多内存搜索或复制功能的优化版本都依赖于它们。
在许多情况下,使用的版本最终还是编译器的内置版本,并且这些都经过了高度优化,甚至比 C 库的优化还要多(例如,
memcpy
通常会转换为寄存器加载和存储,或者甚至是一个固定的商店)。我记得我必须在 2006 年修复 Solaris 中的内核核心转储错误,该错误是由 ISO-9660 + Rock Ridge 文件系统触发的,该文件系统由
mkisofs
.该 ISO 格式化软件没有在 ISO-9660 目录条目的中间包含 Rock Ridge 文件名(由 完成
mkisofs
),而是在 ISO-9660 目录条目的末尾。现在您需要知道 Rock Ridge 文件名不会以空字节结尾...发生的情况是 Solaris 内核中的(当时优化过多)字符串例程在某些情况下可能会超调 1,如果 Rock Ridge 文件名恰好在 2k 扇区的末尾结束,而该扇区正好在末尾结束对于 4k 内核内存页面,这种过冲访问由于非法内存访问而导致内核崩溃。
我们需要将访问代码重写为非常保守,以防止将来出现这种内核恐慌。
如您所见,有时为内核编写安全代码要困难得多,而这样的代码有时会慢一些,只是为了避免内核恐慌。
顺便说一句:如果有可能到达 MMU 页面的末尾,则可以通过让链接器在段后添加几个字节来处理用户空间程序中可能无法预测的 CPU 预取问题。这在依赖于映射区域的内核中不起作用。