如何在Linux内核上进行64位分割?

时间:2018-08-06 13:00:03

标签: c linux-kernel

我想在linux内核(32位处理器)上执行以下代码:

#define UQ64 long long int
#define UI32 long int

UQ64 qTimeStamp;
UQ64 qSeconds;
UI32 uTimeStampRes;

qTimeStamp = num1;
uTimeStampRes = num2;

// 64 division !
qSeconds = qTimeStamp / uTimeStampRes;

有一种算法可以计算64分度? 谢谢。

2 个答案:

答案 0 :(得分:2)

您可以在任何位计算机上划分任意大小的数字。唯一的区别是分割的方式。在本机处理64位整数的处理器上,它将是一条机器代码指令(我不知道没有硬件划分的任何64位处理器)。在具有较窄寄存器的处理器上,它将被翻译为一系列机器代码指令或对划分这64位数字的库函数的调用:

uint64_t foo(uint64_t x, uint64_t y)
{
    return x/y;
}

在amd64指令集上:

        mov     rax, rdi
        xor     edx, edx
        div     rsi
        ret

在ia32指令集上:

sub     esp, 12
push    DWORD PTR [esp+28]
push    DWORD PTR [esp+28]
push    DWORD PTR [esp+28]
push    DWORD PTR [esp+28]
call    __udivdi3
add     esp, 28
ret

答案 1 :(得分:2)

GCC C编译器生成的代码调用libgcc库中的函数,以在32位CPU上使用64位操作数实现/%操作。但是,Linux内核链接到libgcc库,因此在为32位Linux内核构建代码时,此类代码将无法链接。 (在构建外部内核模块时,在您尝试将模块动态加载到运行的内核中之前,问题可能并不明显。)

最初,Linux内核仅具有do_div(n,base)定义的#include <asm/div64.h>宏。此宏的用法很不常见,因为它修改了第一个参数 inplace 成为除法所得的商,并产生(返回)除法的余数作为结果。这样做是出于代码效率的原因,但是使用起来有些麻烦。此外,它仅支持将64位无符号除数除以32位除数。

Linux内核版本2.6.22引入了#include <linux/math64.h>头文件,该头文件定义了一组函数,这些函数比旧的do_div(n,base)宏更全面,并且因为它们的行为类似于普通的C函数而更易于使用。

#include <linux/math64.h>声明的用于64位除法的函数如下所示。除非另有说明,否则所有这些都自内核版本2.6.26起可用。

italics 中下面列出的功能之一从内核版本4.18-rc8起不存在。谁知道它是否会实施? (由头文件声明的其他一些与更高版本的内核中的乘法和移位操作有关的功能在下文中已省略。)

  • u64 div_u64(u64 dividend, u32 divisor)-64位除数除以32位除数的无符号除法。
  • s64 div_s64(s64 dividend, s32 divisor) —签名的64位除数除以32位除数。
  • u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)-将64位除数除以32位除数,然后除以余数。
  • s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) —用64位除数除以32位除数并除以余数。
  • u64 div64_u64(u64 dividend, u64 divisor)-64位除数的无符号除以64位除数。
  • s64 div64_s64(s64 dividend, s64 divisor)(自2.6.37开始)签署了64位除数除以64位除数的方法。
  • u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)(自3.12.0开始)将64位除数除以64位除数,然后除以余数。
  • s64 div64_s64_rem(s64 dividend, s64 divisor, s64 *remainder) (截至4.18-rc8尚不存在)对64位除数除以64位除数,并进行除数。< / li>
  • div64_long(x,y)(自3.4.0版本起)宏,用于对long int除数(32位或64位)进行64位除数的有符号除法,具体取决于架构)。
  • div64_ul(x,y)(自3.10.0开始)宏,可将unsigned long int除数(32位或64-位,具体取决于架构)。
  • u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)-通过重复从除数中除以除数,除以余数(如果预期除数不会比被乘数大很多,则可能比常规除法快)对64位除以32位除数进行无符号除法。除数)。