内核函数 do_div() 与 undefined reference to __udivdi3
来源:互联网 发布:js中数组存储对象 编辑:程序博客网 时间:2024/06/10 05:16
【问题】
编译Linux下面的代码,经常会遇到这种错误:
undefined reference to `__udivdi3'
【解决过程】
之前遇到过几次了,都是类似的原因导致此问题的。后来才了解,其根本原因:
嵌入式中,32位系统中(目前多数系统都是,比如ARM的片子),对于普通的a除以b(b为32位):
(1)当a为32位,Linux 内核中,常用uint32_t 类型,可以直接写为 a/b
(2)但是,对于a是64位,uint64_t的时候,就要用到专门的除操作相关的函数,linux内核里面一般为
do_div(n, base),注意,此处do_div得到的结果是余数,而真正的a/b的结果,是用a来保存的。
do_div(n,base)的具体定义,和当前体系结构有关,对于arm平台,在
arch/arm/include\asm\div64.h
其实现很复杂,感兴趣的自己去代码里看吧,这里不多说了。
因此,如果你当前写代码,a/b,如果a是uint64_t类型,那么一定要利用do_div(a,b),而得到结果a,
而不能简单的用a/b,否则编译可以正常编译,但是最后链接最后出错,会提示上面的那个错误:
undefined reference to "__udivdi3"
【解决方法】
知道原因,就好办了。办法就是,去你代码里面找到对应的用到除法的地方,即类似于a/b的地方,其中被除数a为64位,Linux中一般用用uint64_t,将a/b用do_div(a,b)得到的a去代替(注意,不是直接用do_div()得到真正a除b后的结果,因为do_div(a,b)得到的是余数,囧。。。),即可,而具体写其他,就显得很麻烦。此处,我们可以借鉴Linux中\fs\yaffs2\yaffs_fs.c中的宏:
static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
{
uint64_t result = partition_size;
do_div(result, block_size);
return (uint32_t)result;
}
来自己也去封装一个支持64位数的除法的函数,不过,Linux内核就是好,早已经帮我们实现了对应的64位的unsingned和signed两个函数:
static inline u64 div_u64(u64 dividend, u32 divisor);
static inline s64 div_s64(s64 dividend, s32 divisor);
我们可以直接拿过来用了,注意用此函数时,要包含对应头文件:
#include <linux/math64.h>
总结一下就是:
1.先包含头文件:
2.然后用(a,b)得到a/b的结果即可。
【提示】
如果需要在进行64位除数的时候,同时得到余数remainder,可以直接用
static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder);
static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
【引用】
1. - 64 bit division in linux
If you've encountered an error message like this
Unknown symbol __udivdi3Unknown symbol __umoddi3Unresolved symbol __udivdi3Unresolved symbol __umoddi3
you most likely want to make a 64 bit division, which is not supported by default in linux kernel space.
To solve this problem, you need to use the do_div macro available in asm/div64.h:
#include <asm/div64.h>unsigned long long x, y, result;unsigned long mod;mod = do_div(x, y);result = x;
If you want to calculate x / y with do_div(x, y), the result of the division is in x, the remainder is returned from the do_div function.
Since do_div is just an asm (assembler) macro, it doesn't break real time determinism, so it's also suitable for use in RTAI classic, RTAI fusion and ADEOS/ADEOS-IPIPE applications.
本文来自:http://hi.baidu.com/serial_story/blog/item/8ff17654ecae9e58574e0018.html
- 内核函数 do_div() 与 undefined reference to __udivdi3
- linux内核函数do_div与undefined reference to `__udivdi3'解决方法
- 内核函数 do_div() 与 undefined reference to __udivdi3
- undefined reference to `__udivdi3'
- undefined reference to __udivdi3问题之解决
- undefined reference to '_modsi3'和`__udivdi3'
- undefined reference to '_modsi3'和`__udivdi3'问题的分析与解决办法
- C++虚函数 undefined reference to ***
- undefined reference to vtable 原因与解决办法
- undefined reference to vtable 原因与解决办法
- undefined reference to 'floor'/undefined reference to `&
- undefined reference to 'floor'/undefined reference to
- 编译内核是发现错误:undefined reference to `dm9000_initialize'
- 编译内核出现问题: undefined reference to `__gnu_mcount_nc'
- ----linux--内核编译的问题:undefined reference to `printascii'
- A20内核编译错误undefined reference to `hwmon_device_register'
- 内核2.6.22.6编译出现 undefined reference to __mutex_unlock_slowpath,
- 编译3.10内核 出现错误 “undefined reference to...." 解决方法
- [转]GroupCache:Go 语言实现的 memcached
- 学习轮滑
- Controller and Concurrency
- VBA给合并单元格黏贴赋值
- 你好 凯旋归来 12:20:16 PM 我下载的你们网站的短链接生成工具打不开是怎么回事 凯旋归来 12:21:09 PM 请你们远程帮我打开你好 凯旋归来 12:20:16 PM 我下载的你们
- 内核函数 do_div() 与 undefined reference to __udivdi3
- 微博推广
- [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
- vim 修改文件编码
- 使用 libevent 和 libev 提高网络应用性能
- 2014年计算机求职总结--准备篇 (顺便也带点自己在美国准备的总结吧)
- c语言程序
- drop cache
- ThreadLocal的正确用法