c - 如何在 linux 内核上进行 64 位除法?

标签 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位的算法吗? 谢谢。

最佳答案

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

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

Linux 内核版本 2.6.22 引入了 #include <linux/math64.h> header,它定义了一组功能,比旧的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 位除数和余数的除法。
  • div64_long(x,y)(自 3.4.0 起) 宏,用 long int 对 64 位被除数进行有符号除法除数(32 位或 64 位,具体取决于架构)。
  • div64_ul(x,y)(自 3.10.0 起) 宏对 64 位被除数进行无符号除法 unsigned long int除数(32 位或 64 位,具体取决于架构)。
  • u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) — 64 位除法除以 32 位除数的无符号除法,方法是从被除数中重复减去除数,余数(如果被除数预计不会比除数大很多,则可能比常规除法更快)。

关于c - 如何在 linux 内核上进行 64 位除法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51708273/

相关文章:

linux - 从另一个进程中捕获异常

c - 什么内核代码被破坏了?

c - gcc 预处理器 typedef 名称替换

c++ - 将 SFML 客户端连接到 C 服务器

c - while 在 C 中使用嵌套 scanf 循环

linux - 每次我对 linux 内核做一点改动时,我是否应该安装 modules_install

linux - 如何在 linux 内核代码(即 x86、x86_64)中读取 cpu 类型?

微 Controller 类型转换改进

c - 为什么 WIFEXITED 会在运行过程中返回 True?

ubuntu - 构建自定义内核后没有模块 -> "cannot access/lib/modules/xyz: No such file or directory"