*******************************************************************************************************************************************************
作者:EasyWave 时间:2015.02.21
类别:Linux应用-嵌入式Linux下GCC编译器__sync_sub_and_fetch_4错误的解决心得 声明:转载,请保留链接
注意:如有错误,欢迎指正。这些是我学习的日志文章......
*******************************************************************************************************************************************************
一:多线程下变量的GCC原子操作
原子操作就是不可再分的操作,在多线程程序中原子操作是一个非常重要的概念,它常常用来实现一些同步机制。在Linux系统中的GCC或者嵌入式Linux的交叉编译GCC中从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作。其声明如下所示:
这两组函数的区别在于第一组返回更新前的值,第二组返回更新后的值。注意:type可以是1,2,4或8字节长度的int类型,即:
int8_t / uint8_t
int16_t / uint16_t
int32_t / uint32_t
int64_t / uint64_t
这两组函数的后面的可扩展参数(...)用来指出哪些变量需要memory barrier,因为目前GCC实现的是full barrier(类似于linux
kernel 中的mb(),表示这个操作之前的所有内存操作不会被重排序到这个操作之后),所以可以略掉这个参数。
二:undefined reference to ‘__sync_sub_and_fetch_4‘ problem如何解决
在有些嵌入式Linux的交叉编译GCC环境中可能并没有这类进程下的原子操作函数,也有可能是uClibc库比较老的原因导致的,我在编译BlueZ时,就发现了当uClibc和GCC编译器版本太老时,有很多的系统函数是没有的,在编译BlueZ时会出现很多没有见过的错误。最难搞定就是undefined
reference to ‘__sync_sub_and_fetch_4‘ problem的错误,后来在国外的网站上发现一个解决方式,那就是到高版本中的GCC中下载一个linux_atomic.c文件,将其编译为一个静态库链接到你的具体编译的项目代码中可以解决这个错误。由于我的嵌入式Linux的GCC交叉编译工具比较低,还是4.3 的版本,也许在做交叉编译工具时并没有将线程下原子操作函数做进来而导致undefined
reference to ‘__sync_sub_and_fetch_4‘ problem的问题发生,在ftp://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/releases/gcc-4.6.0/下载一个4.6版本的GCC下来,如下所示:
对于相应的嵌入式Linux的线程下原子操作函数,一般是放在gcc/config/xxxx/linux-atomic.c下,xxxx就是不同的架构的目录,比如:ARM的平台,就是在gcc/config/arm/linux-atomic.c,如下所示:
采用libtool工具来编译linux-atomic.c文件,可以得到一个静态库,将这个静态库加入到你的实际项目中就可以解决这个问题,具体的做法如下:
#!/bin/bash AR="arm-linux-uclibcgnueabi-ar" RANLIB="arm-linux-uclibcgnueabi-ranlib" CC="arm-linux-uclibcgnueabi-gcc" libtool --tag=CC --mode=compile arm-linux-uclibcgnueabi-gcc -g -O2 -MT linux-atomic.lo -MD -MP -MF linux-atomic.Tpo -c -o linux-atmoic.lo linux-atomic.c libtool --tag=CC --mode=link arm-linux-uclibcgnueabi-gcc -module -avoid-version -g -O2 -o liblinux-atmoic.la linux-atmoic.lo
我这里做了一个脚本,将其命名为:build.sh就可以了,将linux-atomic.c和build.sh放在同一目录下,然后执行./build.sh即可。具体的操作见下图所示:
最后将liblinux-atmoic.a加入到你的实际要编译的程序LIBS中即可。具体可以自己在LIBS="-llinux-atmoic"加入这选项。重新编译linux-atomic.c并且将其加入到要编译的项目中就可以解决undefined
reference to ‘__sync_sub_and_fetch_4‘ problem这类的错误。