添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

【解决过程】

之前遇到过几次了,都是类似的原因导致此问题的。后来才了解,其根本原因:

嵌入式中,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://yijunzhu.diandian.com/?tag=%E5%86%85%E6%A0%B8 编译 Linux 下面的代码,经常会遇到这种错误: undefined reference to ` __ udivdi 3 ' 【 解决 过程】 ...
undefined reference to ` __modsi 3 '和 ` __ udivdi 3 '问题的分析 解决 办法 嵌入式开发交流群280 3 52802,欢迎加入! 【编译器版本】 arm - linux - gcc 3 .4.1 【问题描述】 在做嵌入式底层开发时(基于ARM编译无OS的程序),编写整数转字符串 函数 ,用到了求余操作%和除数操作,部分代码如下: while(num) deno...
[ 17.940000] qca_ol: Unknown symbol __ udivdi 3 (err 0) insmod: can't insert '/lib/modules/qca_ol.ko': unknown symbol in module, or unknown parameter         这个错误导致qca_ol.ko无法 pwm_dev = rt_device_find(PWM_DEV_NAME); if (!pwm_dev) { rt_kprintf("PWM device not found\n"); return; /* 打开设备 */ if (rt_device_open(pwm_dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) { rt_kprintf("Open device failed\n"); return; /* 配置通道1(PE9) */ rt_pwm_set(pwm_dev, CHANNEL1, 1000000, 500000); // 周期1ms, 占空比50% rt_pwm_enable(pwm_dev, CHANNEL1); // 启用输出 /* 配置通道2(PE11) */ rt_pwm_set(pwm_dev, CHANNEL2, 2000000, 1500000); // 周期2ms, 占空比75% rt_pwm_enable(pwm_dev, CHANNEL2); // 启用输出 while(1) __WEAK void SystemClock_Config(void) RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regula to r output voltage __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULA TO R_VOLTAGE_SCALE1); /** Initializes the RCC Oscilla to rs according to the specified parameters * in the RCC_OscInitTypeDef structure. RCC_OscInitStruct.Oscilla to rType = RCC_OSCILLA TO RTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 4; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_ DIV 2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler(); /** Initializes the CPU, AHB and APB buses clocks RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLK Div ider = RCC_SYSCLK_ DIV 1; RCC_ClkInitStruct.APB1CLK Div ider = RCC_HCLK_ DIV 4; RCC_ClkInitStruct.APB2CLK Div ider = RCC_HCLK_ DIV 2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) Error_Handler(); 但是报错: linking... ./rt - thread/src/components.o: In function ` main_thread_entry&# 3 9;: F:\Code_Test\keil_test\car\brain\Debug/../rt - thread/src/components.c:198: undefined reference to ` main&# 3 9; collect2.exe: error: ld returned 1 exit status make: *** [makefile:85: rtthread.elf] Error 1 "make - j12 all" terminated with exit code 2. Build might be incomplete.
报错如下: 通过参考博客:http://blog.chinaunix.net/uid - 20717979 - id - 3 3 51 3 60.html 后发现是数据类型问题,但是作者提供的思路没有 解决 ,于是去lib/printfmt.c文件中做类型强转换后运行成功 printnum(putch, putdat, num / base, base, width - 1, padc); printnum(putch, putdat, (uint 3 2_t)num / (uint 3 2_t)base, bas