xml version="1.0" encoding="utf-8" standalone="yes"12bet++博客-Prayerhttp://www.fometaux.com/prayer/在一般中寻求卓越zh-cnWed, 03 Apr 2019 21:13:08 GMTWed, 03 Apr 2019 21:13:08 GMT6012bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/04/03/216328.htmlPrayerPrayerWed, 03 Apr 2019 07:56:00 GMThttp://www.fometaux.com/prayer/archive/2019/04/03/216328.htmlhttp://www.fometaux.com/prayer/comments/216328.htmlhttp://www.fometaux.com/prayer/archive/2019/04/03/216328.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216328.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216328.html

本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具。ldd是用来分析程序运行时需要依赖的动态库的工具;nm是用来查看指定程序中的符号表相关内容的工具。下面通过例子,分别来介绍一下这两个工具:

1. ldd, 先看下面的例子, 用ldd查看cs程序所依赖的动态库:

  1. $ ldd cs  
  2. linux-gate.so.1 =>  (0xffffe000)  
  3. libz.so.1 => /lib/libz.so.1 (0xb7f8c000)  
  4. libpthread.so.0 => /lib/libpthread.so.0 (0xb7f75000)  
  5. libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8 (0xb7e4d000)  
  6. libpcre.so.0 => /usr/lib/libpcre.so.0 (0xb7e21000)  
  7. libstd12bet.so.6 => /usr/local/gcc4.5.1/lib/libstd12bet.so.6 (0xb7d40000)  
  8. libm.so.6 => /lib/libm.so.6 (0xb7d18000)  
  9. libgcc_s.so.1 => /usr/local/gcc4.5.1/lib/libgcc_s.so.1 (0xb7cfd000)  
  10. libc.so.6 => /lib/libc.so.6 (0xb7bbc000)  
  11. /lib/ld-linux.so.2 (0xb7fab000)  
  12. libdl.so.2 => /lib/libdl.so.2 (0xb7bb7000)  

在上面的例子中,ldd的结果可以分为三列来看:

•第一列:程序需要依赖什么库
•第二列: 系统提供的与程序需要的库所对应的库
•第三列:库加载的开始地址
通过上面的信息,我们可以得到以下几个信息:

•(1) 通过对比第一列和第二列,我们可以分析程序需要依赖的库和系统实际提供的,是否相匹配
•(2) 通过观察第三列,我们可以知道在当前的库中的符号在对应的进程的地址空间中的开始位置
2. nm, 通过下面的例子,我们来介绍nm工具:

先看一下这个简单的程序:

  1. #include "iostream"   
  2.    
  3. using namespace std;  
  4.    
  5. class Test  
  6. {  
  7. public:  
  8.     void Hello()  
  9.     {  
  10.         cout < < "Hello world!" << endl;  
  11.     }  
  12. };  
  13.    
  14. int main()  
  15. {  
  16.     Test test;  
  17.     test.Hello();  
  18. }  

接下来,我们编译该程序,然后看nm的结果:

  1. $ g++ test.cc -o test  
  2. c$ nm test  
  3. 08049f10 d _DYNAMIC  
  4. 08049ff4 d _GLOBAL_OFFSET_TABLE_  
  5. 080486f0 t _GLOBAL__I_main  
  6. 080487fc R _IO_stdin_used  
  7.          w _Jv_RegisterClasses  
  8. 080486b0 t _Z41__static_initialization_and_destruction_0ii  
  9. 0804870c W _ZN4Test5HelloEv  
  10.          U _ZNSolsEPFRSoS_E@@GLIBCXX_3.4  
  11.          U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4  
  12.          U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4  
  13. 0804a040 B _ZSt4cout@@GLIBCXX_3.4  
  14.          U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4  
  15. 0804a0d4 b _ZStL8__ioinit  
  16.          U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4  
  17. 08049f00 d __CTOR_END__  
  18. 08049ef8 d __CTOR_LIST__  
  19. 08049f08 D __DTOR_END__  
  20. 08049f04 d __DTOR_LIST__  
  21. 080488c8 r __FRAME_END__  
  22. 08049f0c d __JCR_END__  
  23. 08049f0c d __JCR_LIST__  
  24. 0804a02c A __bss_start  
  25.          U __cxa_atexit@@GLIBC_2.1.3  
  26. 0804a024 D __data_start  
  27. 080487b0 t __do_global_ctors_aux  
  28. 08048610 t __do_global_dtors_aux  
  29. 0804a028 D __dso_handle  
  30.          w __gmon_start__  
  31.          U __gxx_personality_v0@@CXXABI_1.3  
  32. 080487aa T __i686.get_pc_thunk.bx  
  33. 08049ef8 d __init_array_end  
  34. 08049ef8 d __init_array_start  
  35. 08048740 T __libc_csu_fini  
  36. 08048750 T __libc_csu_init  
  37.          U __libc_start_main@@GLIBC_2.0  
  38. 0804a02c A _edata  
  39. 0804a0d8 A _end  
  40. 080487dc T _fini  
  41. 080487f8 R _fp_hw  
  42. 08048508 T _init  
  43. 080485e0 T _start  
  44. 0804a0cc b completed.7065  
  45. 0804a024 W data_start  
  46. 0804a0d0 b dtor_idx.7067  
  47. 08048670 t frame_dummy  
  48. 08048694 T main  

上面便是test这个程序中所有的符号,首先需要介绍一下上面的内容的格式:

•第一列:当前符号的地址
•第二列:当前符号的类型
•第三列:当前符号的名称
在上面的结果中,像_ZN4Test5HelloEv这样的符号,很多读者朋友可能会被它搞晕,这里介绍个小技巧,在nm的时候,加上-C选项,就可以把这些难以识别的符号,转换成便于我们阅读的符号TestHello()。这个主要是12bet中的mangle机制所导致的,加上-C就是指定列出的符号是demangle了的。说了这么多,到底nm对我们程序有啥具体的帮助呢,我觉得主要有以下几个方面:
(1)判断指定程序中有没有定义指定的符号 (比较常用的方式:nm -C proc | grep symbol)
(2)解决程序编译时undefined reference的错误,以及mutiple definition的错误

(3)查看某个符号的地址,以及在进程空间的大概位置(bss, data, text区,具体可以通过第二列的类型来判断)

本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具。ldd是用来分析程序运行时需要依赖的动态库的工具;nm是用来查看指定程序中的符号表相关内容的工具。下面通过例子,分别来介绍一

相关推荐



Bwin平台 2019-04-03 15:56 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/25/216311.htmlPrayerPrayerMon, 25 Mar 2019 03:41:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/25/216311.htmlhttp://www.fometaux.com/prayer/comments/216311.htmlhttp://www.fometaux.com/prayer/archive/2019/03/25/216311.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216311.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216311.htmldb2安装完成后,tcp/ip连接端口默认为50000,可通过下面的方法确认:

 

1、使用命令 db2 get dbm cfg |find "SVCENAME" 查找到TCP/IP 服务名

 

2、到系统配置文件里找到service name 对应的 port number
windows:查看 c:\windows\system32\drivers\etc\services                                                

aix:         查看 /etc/services

如下:

DB2_DB2              60000/tcp
DB2_DB2_1          60001/tcp
DB2_DB2_2          60002/tcp
DB2_DB2_END      60003/tcp

db2c_DB2             50000/tcp

 

3、使用 netstat -an 命令查找tcp/ip 服务的端口

 
4、修改端口号
   直接修改services文件中当前服务名对应的端口号
如:db2c_DB2 50000/tcp
然后重启数据库即OK  db2stop  db2start

5、另外附上一个关于linux系统下的查找方法(摘抄帖子):

In JDBC configurations for WPA, you have to specify the port that DB2 is listening on. I usually look for /etc/services or try one of 50000/50001 and it usually works. In SUSE Linux, both the solutions did not work and there was another process (Multithreaded routing toolkit aka mrt) was listening on port 50000.

So how do we find out the DB2 port in a reliable way? Read on...
Step 1: Set the DB2 environment.
$ . ~db2inst1/sqllib/db2profile

Step 2: Find the service name for DB2 instance. It basically involves running "db2 get dbm cfg" command and finding a line containing SVCENAME. 
$ svc=`db2 get dbm cfg | grep SVCENAME | cut -d= -f2 | awk '{print $1}'`

Step 3: Find the service name that you got from Step 2 in /etc/services or %SYSTEMROOT%\system32\drivers\etc\services. That is the port DB2 is listening on. $ grep $svc /etc/services

 

Hope you find this useful.




用sqoop做测试,发现端口号50000被占用了,所以就更改了一下DB2的端口号。


第一步,登录DB2数据库的实例用户,我这里是db2inst1

db2 get dbm cfg|grep SVCENAME

可以看到对应的SVCENAME的名称是什么。

clipboard.png


这里容易出现一个问题。按照网上有人说的,会将SVCENAME改为端口号,那个是错误的。一定要将这个名称和services中的名称统一。


第二步,退回到root用户,

vim /etc/services,找到对应的SVCENAME的名称所对应的端口号。

我这里直接编辑成50001

clipboard.png

第三步,先关数据库,再开就可以了。

db2stop

db2start


实际上没有复杂的步骤,只是好多人写的比较的乱,还不加解释说明,所以坑了些。



可以通过db2 get dbm cfg,查询数据库管理器配置参数,就可以查到端口号或端口名。

示例:

$ db2 get dbm cfg | grep -i svcTCP/IP Service name (SVCENAME) = 50000

50000就是端口号了。


如果查到的是端口名,可以通过网络服务配置文件来找到对应关系。

示例:

$ db2 get dbm cfg | grep -i svc

TCP/IP Service name (SVCENAME) = db2c_DB2

这时,就需要查找db2c_DB2对应的端口号了。

$ cat /etc/services | grep db2c_DB2

db2c_DB2 60000/tcp

这个60000就是端口号了。

如果DB2是装在windows的server上,那么就需要查找这个配置文件了,C:\WINDOWS\system32\drivers\etc\services格式:db2c_DB2 50000/tcp





Bwin平台 2019-03-25 11:41 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/21/216305.htmlPrayerPrayerThu, 21 Mar 2019 06:46:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/21/216305.htmlhttp://www.fometaux.com/prayer/comments/216305.htmlhttp://www.fometaux.com/prayer/archive/2019/03/21/216305.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216305.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216305.htmlhttps://zhidao.baidu.com/question/337623541.html

整个文件视图不见了可以按CTRL+U按出来,FTP视图不见了。可以点击高级项--》配置--》FTP选项--》在浏览器视图里显示FTP帐户。

Bwin平台 2019-03-21 14:46 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/20/216304.htmlPrayerPrayerWed, 20 Mar 2019 07:28:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/20/216304.htmlhttp://www.fometaux.com/prayer/comments/216304.htmlhttp://www.fometaux.com/prayer/archive/2019/03/20/216304.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216304.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216304.html来自:http://www.cnblogs.com/nobugtodebug/archive/2012/11/07/e6cd72c67b3dd843f40d7ce919f7336a.html

动态库(.so)链接静态库(.a)的情况总结 
一般来说在链接时想要使用静态库有三种方法:
1、link时加上 -static 选项;当加上 -static选项后,gcc会把所有用到的库都做静态连接。
2、link时直接指定想要静态连接的.a文件的绝对路径。优点是除非.a文件不存在,否则肯定有效;缺点也是很明显,拿到其他机器上编译时,.a文件也必须在相同的路径下存放。
3、在要静态连接的库前指定-Bstatic ,在要动态连接的库前指定-Bdynamic选项。连接器在看到-Bstatic时会优于去找静态库,如果找不到再去找动态库。 -Bdynamic也是同样的情况。可是我实验的结果是这两个选项根本不起作用,我的环境是centos 6.2 gcc4.7.2, 仔细看了gcc 文档,这两个选项是针对VxWorks平台的,所以不起作用。
 
当我们要编译一个so提供给外部使用,这个so本身依赖一些第三方库。但是我们却希望so的使用者不用关心该so对其他库的依赖。很自然的是会想到在编译so的时候把依赖到的第三方库静态链接进来。
我在这样做的时候碰到了问题:指定-static选项时,link失败,错误提示说要用到的object文件应该用-fPIC选项重新编译才行(也就是说,只有用-fPIC选项编译的object文件能被link到.so里);当直接给出.a的绝对路径的时候link成功,但是.so里却并没有直正包含所用到的符合连接。针对碰到的问题,我做了一些实验。实验如下:
static.c

#include <stdio.h>
 
const char* sz_static = "i'm a static str.";
 
void print_niuzai_said()
{
    printf("in static lib, niu zai said, i'm happy!\n");
}

dynamic.c
 
#include <stdio.h>
#include "static.h"
 
void print_papa_said()
{
    print_niuzai_said();
    printf("in dynamic lib, papa said, niu zai is wonderful!\n");
}
 

main.c
 
#include <unistd.h>
#include "dynamic.h"
 
int main(int argc, char** argv)
{
    print_papa_said();
    return 0;
}
分别用两组命令编译出了两个.a 文件
1、gcc -o static.o -c static.c
      ar -r libstatic.a static.o
2、gcc -o static_shared.o -shared -fPIC -c static.c
      ar -r libstatic_shared.a static_shared.o
 
然后用此命令  "gcc -o dynamic.o -c dynamic.c"  编译出dynamic.o文件
接下来就是本文的主题了,链接生成libdynamic.so.此时有这么几种情况:
1、使用 "gcc -o libdynamic.so -shared -fPIC -L. -lstatic dynamic.o ",连接成功,但.so里实际上没有static.o里的内容。
2、使用"gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic",连接失败 
3、使用 "gcc -o libdynamic.so -shared -fPIC -L. -lstatic_shared dynamic.o",连接成功,但.so里实际上没有static.o里还是没有的内容。
 
4、使用 "gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic_shared",连接成功,.a的内容被连接到了.so里面。
 
 
另外,链接静态生成可执行程序时,静态库是不是用 "-shared -fPIC" 选项编译产生的没有影响。都能正常生成可执行程序。
综合以上情况,总结如下:
1、动态连接库中用到的object文件必须是用 "-shared -fPIC"选项编译产生的,否则连接时要么报错,要么被忽略。
2、静态库中的object文件最好也用"-shared -fPIC"选项编译,这样静态库就可以同时被连接到.so 或者可执行性文件中。
3、动态库只能连接用"-shared -fPIC"选项编译出来的静态库(和第1点是同一件事)
4、连接选项的顺序对连接器的行为有重要影响!
 
静态库使用-shared -fPIC连接命令连接执行结果动态库结果最终结果
gcc -o libdynamic.so -shared -fPIC -L. -lstatic dynamic.o成功静态库内容没有被连接失败
gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic失败 失败
gcc -o libdynamic.so -shared -fPIC -L. -lstatic_shared dynamic.o成功静态库内容没有被连接失败
gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic_shared成功静态库内容被连接成功
 


Bwin平台 2019-03-20 15:28 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/18/216302.htmlPrayerPrayerMon, 18 Mar 2019 06:42:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/18/216302.htmlhttp://www.fometaux.com/prayer/comments/216302.htmlhttp://www.fometaux.com/prayer/archive/2019/03/18/216302.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216302.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216302.html直接看图:

   

有两个特点:

1:使用-r参数

2:在目录后面使用"."号
 

这样的话就可以把/opt/merkle 目录和子目录里面的文件全部下载到本地了。



Bwin平台 2019-03-18 14:42 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/18/216301.htmlPrayerPrayerMon, 18 Mar 2019 06:27:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/18/216301.htmlhttp://www.fometaux.com/prayer/comments/216301.htmlhttp://www.fometaux.com/prayer/archive/2019/03/18/216301.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216301.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216301.html

当你在linux下写C/12bet代码的时候,是不是会遇到许多编译链接的问题? 时不时报个glibc,gcc,g++等相关的错误? 很多时候都无从下手,而且比较混乱。 这也是编译链接过程中经常出现的问题。

这篇文章不是去介绍如何编译链接,而是理清编译链接过程中碰到的一些概念和出现的问题。尤其是,libc,glib,glibc,eglibc,lib12bet,libstd12bet,gcc,g++。

从libc说起。
libc是Linux下原来的标准C库,也就是当初写hello world时包含的头文件#include < stdio.h> 定义的地方。

后来逐渐被glibc取代,也就是传说中的GNU C Library,在此之前除了有libc,还有klibc,uclibc。现在只要知道用的最多的是glibc就行了,主流的一些linux操作系统如 Debian, Ubuntu,Redhat等用的都是glibc(或者其变种,下面会说到).

那glibc都做了些什么呢? glibc是Linux系统中最底层的API,几乎其它任何的运行库都要依赖glibc。 glibc最主要的功能就是对系统调用的封装,你想想看,你怎么能在C代码中直接用fopen函数就能打开文件? 打开文件最终还是要触发系统中的sys_open系统调用,而这中间的处理过程都是glibc来完成的。这篇文章详细介绍了glibc是如何与上层应用程序和系统调用交互的。除了封装系统调用,glibc自身也提供了一些上层应用函数必要的功能,如string,malloc,stdlib,linuxthreads,locale,signal等等。

好了,那eglibc又是什么? 这里的e是Embedded的意思,也就是前面说到的变种glibc。eglibc的主要特性是为了更好的支持嵌入式架构,可以支持不同的shell(包括嵌入式),但它是二进制兼容glibc的,就是说如果你的代码之前依赖eglibc库,那么换成glibc后也不需要重新编译。ubuntu系统用的就是eglibc(而不是glibc),不信,你执行 ldd –version 或者 /lib/i386-linux-gnu/libc.so.6
(64位系统运行/lib/x86_64-linux-gnu)看看,便会显示你系统中eglibc/glibc的版本信息。 这里提到了libc.so.6,这个文件就是eglibc/glibc编译后的生成库文件。

还有一个glib看起来也很相似,那它又是什么呢?glib也是个c程序库,不过比较轻量级,glib将C语言中的数据类型统一封装成自己的数据类型,提供了C语言常用的数据结构的定义以及处理函数,有趣的宏以及可移植的封装等(注:glib是可移植的,说明你可以在linux下,也可以在windows下使用它)。那它跟glibc有什么关系吗?其实并没有,除非你的程序代码会用到glib库中的数据结构或者函数,glib库在ubuntu系统中并不会默认安装(可以通过apt-get install libglib2.0-dev手动安装),著名的GTK+和Gnome底层用的都是glib库。想更详细了解glib? 可以参考这里

看到这里,你应该知道这些库有多重要了吧? 你写的C代码在编译的过程中有可能出现明明是这些库里面定义的变,却量还会出现’Undefined’, ‘Unreference’等错误,这时候你可能会怀疑是不是这些库出问题了? 是不是该动手换个gilbc/eglibc了? 这里强调一点,在你准备更换/升级这些库之前,你应该好好思考一下,你真的要更换/升级吗?你要知道你自己在做什么!你要时刻知道glibc/eglibc的影响有多大,不管你之前部署的什么程序,linux系统的ls,cd,mv,ps等等全都得依赖它,很多人在更换/升级都有过惨痛的教训,甚至让整个系统奔溃无法启动。所以,强烈不建议更换/升级这些库!

当然如果你写的是12bet代码,还有两个库也要非常重视了,lib12bet/libstd12bet,这两个库有关系吗?有。两个都是12bet标准库。lib12bet是针对clang编译器特别重写的12bet标准库,那libstd12bet自然就是gcc的事儿了。libstd12bet与gcc的关系就像clang与lib12bet. 其中的区别这里不作详细介绍了。

再说说libstd12bet,glibc的关系。 libstd12bet与gcc是捆绑在一起的,也就是说安装gcc的时候会把libstd12bet装上。 那为什么glibc和gcc没有捆绑在一起呢?
相比glibc,libstd12bet虽然提供了12bet程序的标准库,但它并不与内核打交道。对于系统级别的事件,libstd12bet首先是会与glibc交互,才能和内核通信。相比glibc来说,libstd12bet就显得没那么基础了。

说完了这些库,这些库最终都是拿来干嘛的?当然是要将它们与你的程序链接在一起! 这时候就不得不说说gcc了(当然还有前文提到的clang以及llvm等编译器,本文就不细说它们的区别了)。

你写的C代码.c文件通过gcc首先转化为汇编.S文件,之后汇编器as将.S文件转化为机器代码.o文件,生成的.o文件再与其它.o文件,或者之前提到的libc.so.6库文件通过ld链接器链接在一块生成可执行文件。当然,在你编译代码使用gcc的时候,gcc命令已经帮你把这些细节全部做好了。

那g++是做什么的? 慢慢说来,不要以为gcc只能编译C代码,g++只能编译12bet代码。 后缀为.c的,gcc把它当作是C程序,而g++当作是12bet程序;后缀为.cpp的,两者都会认为是12bet程序,注意,虽然12bet是c的超集,但是两者对语法的要求是有区别的。在编译阶段,g++会调用gcc,对于12bet代码,两者是等价的,但是因为gcc命令不能自动和12bet程序使用的库联接,需要这样,gcc -lstd12bet, 所以如果你的Makefile文件并没有手动加上libstd12bet库,一般就会提示错误,要求你安装g++编译器了。

好了,就说到这,理清这些库与编译器之间的关系,相信会对你解决编译链接过程中遇到的错误起到一点帮助。

如果你的编译器不支持一些新的C/12bet特性,想升级gcc/g++, 这里也给出一个基于ubuntu系统的参考方法。

添加ppa

sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update 

添加ppa,是因为你所用的ubuntu版本的更新源中可能并没有你想要的gcc/g++版本。

安装新版gcc/g++

sudo apt-get install gcc-4.8 sudo apt-get install g++-4.8 

可以到/usr/bin/gcc查看新安装的gcc,g++

配置系统gcc/g++

使用update-alternatives,统一更新gcc/g++

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.6 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8 sudo update-alternatives --config gcc 

数字优先级(如60,80)高的会被系统选择为默认的编译器,也可以执行第三条命令就是来手动配置系统的gcc,此处按照提示,选择4.8版本的即可。

转载:http://www.chongh.wiki/blog/2016/05/25/lib-compile-link/



Bwin平台 2019-03-18 14:27 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/13/216294.htmlPrayerPrayerWed, 13 Mar 2019 08:19:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/13/216294.htmlhttp://www.fometaux.com/prayer/comments/216294.htmlhttp://www.fometaux.com/prayer/archive/2019/03/13/216294.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216294.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216294.html问题描述

回归正题,前段时间项目开发中,实现了一个动态库,封装了一些方法。然后基于这个动态库,实现了一个应用程序。应用程序中含有全局变量A,动态库中也含有全局变量A,当我调用动态库中函数后,发现应用程序的A发生了变化!!!O,My God!对于我这种还没在Linux下做过开发的人来说,一头雾水。。。。。。 于是我尝试着,将A中的变量名称改为B,这样问题也就没有了~~~

原因

应用程序进行链接的时候,动态库中全局变量定义,将会被应用程序中同名的全局变量所覆盖。这样也就造成了,在动态库中修改A变量时,应用程序中的A也发生了变化。

解决方法

在创建动态链接库时,gcc/g++选项中添加编译选项

-Wl,-Bsymbolic.

其中Wl表示将紧跟其后的参数,传递给连接器ldBsymbolic表示强制采用本地的全局变量定义,这样就不会出现动态链接库的全局变量定义被应用程序的同名定义给覆盖了!

Bwin平台 2019-03-13 16:19 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/04/216284.htmlPrayerPrayerMon, 04 Mar 2019 03:45:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/04/216284.htmlhttp://www.fometaux.com/prayer/comments/216284.htmlhttp://www.fometaux.com/prayer/archive/2019/03/04/216284.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216284.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216284.html阅读全文

Bwin平台 2019-03-04 11:45 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/04/216283.htmlPrayerPrayerMon, 04 Mar 2019 03:37:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/04/216283.htmlhttp://www.fometaux.com/prayer/comments/216283.htmlhttp://www.fometaux.com/prayer/archive/2019/03/04/216283.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216283.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216283.html阅读全文

Bwin平台 2019-03-04 11:37 发表评论
]]>
12bet++博客-Prayerhttp://www.fometaux.com/prayer/archive/2019/03/01/216276.htmlPrayerPrayerFri, 01 Mar 2019 09:58:00 GMThttp://www.fometaux.com/prayer/archive/2019/03/01/216276.htmlhttp://www.fometaux.com/prayer/comments/216276.htmlhttp://www.fometaux.com/prayer/archive/2019/03/01/216276.html#Feedback0http://www.fometaux.com/prayer/comments/commentRss/216276.htmlhttp://www.fometaux.com/prayer/services/trackbacks/216276.htmlhttp://blog.itpub.net/283313/viewspace-2139257/

unix平台下,动态连接库的使用有两种方式,link方式和dlopen方式。需要设置LD_LIBRARY_PATH作为查找路径(低版本AIX使用LIBPATH)。link方式是程序启动时加载所有编译时连接的动态库,直到程序结束也不会关闭。dlopen方式是在运行中按照参数指定的方式加载动态库,并可以使用dlclose函数关闭,直到下次再使用dlopen重新加载。因此,link方式无法做到不重启应用程序而更新动态库版本,dlopen方式可以。


各平台动态连接库的编译参数如下。文件wel.c,编译成libwel.so(HPUX为libwel.sl)。

  1. #include <stdio.h>

  2. void welcome(void)
  3. {
  4.     puts("welcome,baby!");
  5. }



 linux:
  编译libwel.so:
   gcc -fPIC -shared -o libwel.so wel.c -lc
    -fPIC  用相对地址定位
    -shared  生成动态连接库


 sco unix open server:
  编译libwel.so:
   cc -K PIC -G -o libwel.so wel.c -lc
    -K PIC  用相对地址定位
    -G  生成动态连接库,包含了-b elf选项


 AIX:
  编译libwel.so:
   xlc -G -bnoentry -o libwel.so wel.c -lc
    -G  指定生成动态连接库
    -bnoentry 动态库无需模块入口(低版本AIX需要此参数)


 HP UX:
  编译libwel.so:
   cc +z -c wel.c
   ld -b -o libwel.sl wel.o -lc
    +z  用相对地址定位
    -b  生成动态连接库


 SUN OS: 很类似SCO,man帮助不全面
  编译libwel.so:
   cc -G -o libwel.so wel.c -lc
    -G  生成动态连接库


link方式使用动态连接库的编译参数如下。文件welcome.c,编译成welcome可执行程序。

  1. extern void welcome(void);

  2. int main(void)
  3. {
  4.         welcome();
  5.         return 0;
  6. }



 linux:
   gcc -rdynamic -o welcome welcome.c -L. -lwel
    -rdynamic  导出所有符号供动态使用


 sco unix open server:
   cc -b elf -o welcome welcome.c -L. -lwel
    -b elf  必须使用ELF的可执行文件格式


 AIX:
   xlc -bdynamic -brtl -o welcome welcome.c -L. -lwel
    -bdynamic 使用动态连接方式,系统默认为此方式
    -brtl  -l参数使用.so为库


 HP UX:
   cc -dynamic -o welcome welcome.c -L. -lwel
    -dynamic 使用动态连接方式,系统默认为此方式


 SUN OS:
  编译libwel.so:
   cc -B dynamic -o welcome welcome.c -L. -lwel
    -B dynamic 使用动态连接方式


dlopen方式,其实就是把打开动态库和查找符号的动作放在程序中执行。因此编译可执行文件与普通的相同,只要连接libdl.so库即可。文件welcome.c,编译成welcome可执行程序。

  1. #include <dlfcn.h>

  2. int main(void)
  3. {
  4.     void *handle;
  5.     void (*welcome)(void);

  6.     handle=dlopen("libwel.so",RTLD_LAZY);
  7.     welcome=dlsym(handle,"welcome");
  8.     (*welcome)();
  9.     return 0;
  10. }



 linux:
   gcc -rdynamic -o welcome welcome.c -ldl
    -rdynamic 导出所有符号供动态使用
    -ldl  用系统libdl.so库dlopen(),dlsym(),dlerror(),dlclose()


 sco unix open server:
   cc -b elf -o welcome welcome.c -lc
    -b elf  以elf格式,动态连接库必须


 AIX:
   xlc -bexpall -o welcome welcome.c -ldl -lc
    -bexpall 使主程序的符号可以被动态库使用


 HP UX:
   cc -o welcome welcome.c -ldl -lc


 SUN OS:
   cc -o welcome welcome.c -ldl -lc



------------------------------------------------------------------------------
参照的man手册:
 cc, ld, ldd, dlopen, dlclose, dlerror, dlsym, CC



另:AIX运行动态库时会加载系统内存统一管理,导致即使程序已退出,编译时仍然认为还在使用而无法覆盖。有两个办法,一是root用户执行slibclean,清理系统加载而无人使用的动态库,另一种是编译的库chmod go-rwx,使得组和其他人无权限,这种库系统会认为用户特有而不加载。


来自 “ ITPUB12bet怎么样 ” ,链接:http://blog.itpub.net/283313/viewspace-2139257/,如需转载,请注明出处,否则将追究法律责任。



Bwin平台 2019-03-01 17:58 发表评论
]]>