c - glibc 使用内核函数
问题描述
我试图从 glibc 源代码中理解这种方法:
26 #if LIBM_SVID_COMPAT
27 /* wrapper sqrtf */
28 float
29 __sqrtf (float x)
30 {
31 if (__builtin_expect (isless (x, 0.0f), 0) && _LIB_VERSION != _IEEE_)
32 return __kernel_standard_f (x, x, 126); /* sqrt(negative) */
33
34 return __ieee754_sqrtf (x);
35 }
36 libm_alias_float (__sqrt, sqrt)
37 #endif
据我从这里了解到,如果程序没有sqrt
从 glibc 中找到该函数的有效实现,它会从内核调用一个硬件函数,即一个特定的机器函数。这是正确的吗?
还有,什么libm_alias_float (__sqrt, sqrt)
意思?
解决方案
GNU C 库的数学函数完全在“glibc”源代码树中实现。他们不依赖操作系统内核做任何事情。在这种情况下,“内核”一词指的是计算内核——一些数学算法的核心,你可能想用手工优化的汇编语言编写的部分。
该函数__kernel_standard_f
命名错误。它包含用于处理数学函数中的错误的通用代码;最好将其命名为__math_domain_error
. 在这种情况下,当它的参数为负时__sqrtf
调用;然后将负责设置为,可能会调用 SVID回调,并返回一个 NaN。(神秘代码 126 告诉它是哪个函数调用它以及为什么调用它。实现是在和。)__kernel_standard_f
__kernel_standard_f
errno
EDOM
matherr
__kernel_standard_f
__kernel_standard_f
sysdeps/ieee754/k_standardf.c
sysdeps/ieee754/k_standard.c
该条件_LIB_VERSION != _IEEE_
与是否启用 POSIX 和/或 SVID 数学错误处理有关;现代数学算法实际上宁愿只在结果中查找 NaN 而不会让库浪费时间设置errno
或调用matherr
,因此有一种机制可以关闭后两者。
如果 to 的参数__sqrtf
不是负数,它会尾部调用,__ieee754_sqrtf
这会执行平方根的实际计算。在 glibc 源代码树中有这个函数的几个替代实现;它的通用、仅限 C 的版本位于sysdeps/ieee754/flt-32/e_sqrtf.c
. (即使按照 glibc 的标准,实现数学函数的文件的名称也很神秘。我不费心去理解它们,我只是做find sysdeps -name '*sqrtf*'
或其他什么。)这个函数还从逻辑开始,以检测否定参数(也是零,无穷大, 和 NaN) 并返回适当的值,但它不会触及errno
. 如果您想了解用于计算平方根的数学技术,请查看此文件。
如果您自己运行上述find
命令,您会发现其他几个名为e_sqrtf.c
; 这些都在以特定 CPU 命名的目录中,其浮点单元具有计算平方根的硬件支持,例如sysdeps/x86_64/fpu/e_sqrt.c
读取
double
__ieee754_sqrt (double x)
{
double res;
asm ("sqrtsd %1, %0" : "=x" (res) : "xm" (x));
return res;
}
因为 x86sqrtsd
指令完成了整个工作。
当为其中一个 CPU 构建时,Glibc 的构建过程将选择其中一个文件,而不是通用 C 版本。这种机制很复杂并且没有完整的文档记录,但是glibc 手册的“维护”附录,特别是它的“源代码布局”和“移植”部分,给出了一个不错的概述。
libm_alias_float (__sqrt, sqrt)
安排__sqrtf
也有名字sqrtf
,只是作为一个弱别名。这对于符合标准是必要的。如果您想了解更多详细信息,请提出单独的问题。
推荐阅读
- java - 在maven pom文件中读取环境变量
- python - 阅读 gtfs 谷歌 transitFeed python
- java - 如何使用 Java Streams 为 HashMap 的多个键插入相同的值
- c# - Blazor 服务注入无法正常工作
- dart - 从 FutureBuilder 导航回页面
- sql - 为什么 SQL 在 varchar 列中将 Varchar 值转换为 Integer?
- c# - 为什么值不会在回发中持续存在?
- iis - IIS 和 ASPNETCORE_ENVIRONMENT 发布的应用程序未使用 web.config 中的值?
- c++ - 有没有办法让用户的主路径作为 Windows 中的字符串?
- postgresql - 如何避免意外删除 postgres 表行?