Linux 64 bit division

本文详细介绍了Linux内核中64位除法的实现方式,包括早期的do_div宏到math64.h中更易用的函数,如div_u64、div_s64等,以及四舍五入的DIV_ROUND_CLOSEST函数。涵盖了从32位到64位不同数据类型的除法操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 了解linux 64位除法

1.介绍

  The GCC C compiler generates code that calls functions in the libgcc library to implement the / and % operations with 64-bit operands on 32-bit CPUs. However, the Linux kernel is not linked against the libgcc library, so such code will fail to link when building code for a 32-bit Linux kernel. (When building an external kernel module, the problem may not be apparent until you try and dynamically load the module into the running kernel.)

  Originally, the Linux kernel only had the do_div(n,base) macro defined by #include <asm/div64.h>. The usage of this macro is unusual because it modifies its first argument in place to become the quotient resulting from the division, and yields (returns) the remainder from the division as its result. This was done for code efficiency reasons but is a bit of a pain to use. Also, it only supports division of a 64-bit unsigned dividend by a 32-bit divisor.

  Linux kernel version 2.6.22 introduced the #include <linux/math64.h> header, which defines a set of functions which is more comprehensive than the old do_div(n,base) macro and is easier to use because they behave like normal C functions.

  The functions declared by #include <linux/math64.h> for 64-bit division are listed below. Except where indicated, all of these have been available since kernel version 2.6.26.

  • u64 div_u64(u64 dividend, u32 divisor) — unsigned division of 64-bit dividend by 32-bit divisor.
  • s64 div_s64(s64 dividend, s32 divisor) — signed division of 64-bit dividend by 32-bit divisor.
  • u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) — unsigned division of 64-bit dividend by 32-bit divisor with remainder.
  • s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) — signed division of 64-bit dividend by 32-bit divisor with remainder.
  • u64 div64_u64(u64 dividend, u64 divisor) — unsigned division of 64-bit dividend by 64-bit divisor.
  • s64 div64_s64(s64 dividend, s64 divisor) — (since 2.6.37) signed division of 64-bit dividend by 64-bit divisor.
  • u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder) — (since 3.12.0) unsigned division of 64-bit dividend by 64-bit divisor with remainder.
  • s64 div64_s64_rem(s64 dividend, s64 divisor, s64 *remainder) — (does not exist yet as of 4.18-rc8) signed division of 64-bit dividend by 64-bit divisor with remainder.
  • div64_long(x,y) — (since 3.4.0) macro to do signed division of a 64-bit dividend by a long int divisor (which is 32-bit or 64 bit, depending on the architecture).
  • div64_ul(x,y) — (since 3.10.0) macro to do unsigned division of a 64-bit dividend by an unsigned long int divisor (which is 32-bit or 64-bit, depending on the architecture).
  • u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) — unsigned division of 64-bit division by 32-bit divisor by repeated subtraction of divisor from dividend, with remainder (may be faster than regular division if the dividend is not expected to be much bigger than the divisor).

2.do_div funciton

 25 # define do_div(n,base) ({                  \
   26     uint32_t __base = (base);               \
   27     uint32_t __rem;                     \
   28     __rem = ((uint64_t)(n)) % __base;           \
   29     (n) = ((uint64_t)(n)) / __base;             \
   30     __rem;                          \
   31  }) 

  64 bit division 结果保存在n中;余数保存在返回结果中。do_div得到的结果是余数,而真正的n/base的结果,是用n来保存的。 因为do_div将商保存在被除数中,把原值覆盖了,所以实际运用时要用临时变量保存被除数。

3.DIV_ROUND_CLOSEST function

  96 #define DIV_ROUND_CLOSEST(x, divisor)(          \                                                      
   97 {                           \
   98     typeof(x) __x = x;              \
   99     typeof(divisor) __d = divisor;          \
  100     (((typeof(x))-1) > 0 ||             \
  101      ((typeof(divisor))-1) > 0 || (__x) > 0) ?  \
  102         (((__x) + ((__d) / 2)) / (__d)) :   \
  103         (((__x) - ((__d) / 2)) / (__d));    \
  104 }                           \
  105 )

  该函数主要进行四舍五入计算使用。例如:3/2=1.5,计算机中的整数运算结果为 3/2=1,经过DIV_ROUND_CLOSEST函数四舍五入运算后,3/2=2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值