分类: 嵌入式
2010-09-06 21:41:14
【问题】 编译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) 来自己也去封装一个支持64位数的除法的函数,不过,Linux内核就是好,早已经帮我们实现了对应的64位的unsingned和signed两个函数: static inline u64 div_u64(u64 dividend, u32 divisor); static inline s64 div_s64(s64 dividend, s32 divisor); #include 总结一下就是: 1.先包含头文件: #include 2.然后用do_div64(a,b)得到a/b的结果即可。 【提示】 如果需要在进行64位除数的时候,同时得到余数remainder,可以直接用#include static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder); 【引用】 1. If you've encountered an error message like this Unknown symbol __udivdi3 Unknown symbol __umoddi3 Unresolved symbol __udivdi3 Unresolved symbol __umoddi3 you most likely want to make a 64 bit division, which is not supported by default in linux kernel space. #include 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. |