对于64位除法,使用/
和do_div
有什么区别?
只是为了提高性能?它是建筑依赖的吗?
答案 0 :(得分:4)
此模块中此宏和函数的用途是优化。内核代码中的注释非常清楚:
/*
* 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.
*/
在内核中使用宏来计算单个步骤中的商和余数,而不是标准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);
Linux内核的目标系统可能没有标准兼容的编译器,并且肯定早于其中一些标准添加,所以它有自己的这些函数版本作为宏,其他一些在同一模块中。
答案 1 :(得分:0)
需要该宏,因为在32位目标平台上,写入“ /”将无法链接。
内核中的C库不是您在用户空间中使用的C库。在用户空间C程序中,如果您的CPU没有64位除法指令,则C库将为您实现64位除法。
即使在32位平台上,也可以使用64位乘法,但是64位除法是不行的,并且会拒绝驱动程序,因为它不会通过编译。