为什么 Linux 内核使用 do_div 而不是 /?

Les*_* Li 2 c linux-kernel

对于 64 位除法,使用/和 有do_div什么区别?只是为了提高性能?它是否依赖于架构?

源代码在这里。

chq*_*lie 6

这个宏和这个模块中的函数的目的是优化。内核代码中的注释非常清楚:

/*
 * do_div() is NOT a C function. It wants to return
 * two values (the quotient and the remainder), but
 * since that doesn't work very well in C, what it
 * does is:
 *
 * - modifies the 64-bit dividend _in_place_
 * - returns the 32-bit remainder
 *
 * This ends up being the most efficient "calling
 * convention" on x86.
 */
Run Code Online (Sandbox Code Playgroud)

宏在内核中用于在单个步骤中计算商和余数,而不是标准 C 中的 2 个操作,可能会产生 2 个除法操作码。

事实上,Intel x86 CPU 用一条指令计算整数除法的商和余数。宏使用内联组件利用这一优势,而C编译器可能不能优化2个独立的计算与/%成单个操作码。

在编写这段代码的时候,大多数编译器都没有,而且除法操作码非常昂贵,所以 Linus 决定使用一个特殊的函数来优化这个计算。

请注意,C 标准为此提供了一组函数(在 中声明<stdlib.h>):

div_t div(int numer, int denom);
ldiv_t ldiv(long int numer, long int denom);
lldiv_t lldiv(long long int numer, long long int denom);
Run Code Online (Sandbox Code Playgroud)

linux 内核针对的系统可能没有符合标准的编译器,并且肯定早于这些标准添加中的一些,因此它具有这些函数的自己版本作为宏,以及同一模块中的其他一些版本。