<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[[实践OK]Linux 动态链接库编程基础，以及生成的动态链接库里的函数和地址查看之nm -D  /usr/local/php/lib/php/extensions/no-debug-non-zts-20180731/memcache.so ]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Mon, 08 Dec 2008 02:33:31 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	动态链接库是一种通用的软件组件技术，是多种操作系统中提供基本服务的方式。比如Win32内核就是3个DLL文件构成。这种技术在Linux操作系统下也有对应的实现，就是Linux标准对象Standard Ojbect，对应的文件扩展名为.so。<br/><br/>&nbsp;&nbsp;下面通过一个简单的例子开始介绍Linux标准对象。<br/>&nbsp;&nbsp;我们的标准对象文件含有一个函数，不需要声明export导出符号，只需要编译器设置即可。如下：<br/><div class="code">#include &lt;stdio.h&gt;<br/>#include &lt;stdlib.h&gt;<br/><br/>void show() &#123;<br/>&nbsp;&nbsp;printf(&quot;Standard Object by gashero&#92;n&quot;);<br/>&#125;</div><br/><br/>&nbsp;&nbsp;保存为myso.c文件，按照如下编译：<br/><div class="code">$ gcc -fPIC -shared -o libmyso.so myso.c</div><br/><br/>&nbsp;&nbsp;执行生成一个libmyso.so文件，按照Linux标准对象的命名惯例，应该在库名称之前加上&quot;lib&quot;前缀，尽管不是必须的。编译开关-fPIC代表函数符号可以重定向，-shared代表编译结果是一个标准对象。<br/><br/>&nbsp;&nbsp;不同于Win32DLL，Linux标准对象中的所有函数都是直接导出的，都可以被调用程序所访问。下面我们编写调用程序：<br/><div class="code">#include &lt;stdio.h&gt;<br/><br/>int main() &#123;<br/>&nbsp;&nbsp;printf(&quot;Invoke my so&#92;n&quot;);<br/>&nbsp;&nbsp;show();<br/>&nbsp;&nbsp;return 0;<br/>&#125;</div><br/><br/>&nbsp;&nbsp;保存为invoke.c，按照如下gcc开关编译：<br/><br/><div class="code">$ gcc -o test invoke.c ./libmyso.so</div><br/><br/>&nbsp;&nbsp;编译生成test可执行文件。如上编译条件的最后一条需要是所调用的标准对象文件名，注意必须含有路径。如果只是使用libmyso.so，则必须确保这个文件在可访问的PATH下面。本例所使用的文件名&quot;./libmyso.so&quot;是当前路径下的，使用了相对路径。<br/><br/>&nbsp;&nbsp;如下测试结果：<br/><br/><br/><div class="code">$ ./test<br/>Invoke my so<br/>Standard Object by gashero</div><br/><br/>&nbsp;&nbsp;希望上文的例子可以对大家有所帮助。<br/><br/>如何在 Linux 下调试动态链接库<br/><br/>大家都知道在 Linux 可以用 gdb 来调试应用程序，当然前提是用 gcc 编译程序时要加上<br/><br/><br/><div class="code">-g 参数</div>。<br/>我这篇文章里将讨论一下用 gdb 来调试动态链接库的问题。<br/><br/><br/>&nbsp;&nbsp;首先，假设我们准备这样的一个动态链接库：<br/><br/>QUOTE:<br/>库名称是： ggg<br/>动态链接库文件名是： libggg.so<br/>头文件是： get.h<br/>提供这样两个函数调用接口：<br/><br/><div class="code">&nbsp;&nbsp;&nbsp;&nbsp;int get ();<br/>&nbsp;&nbsp;&nbsp;&nbsp;int set (int a);</div><br/><br/>要生成这样一个动态链接库，我们首先编写这样一个头文件：<br/>CODE:<br/><br/><div class="code">/************关于本文档********************************************<br/>*filename: get.h<br/>*purpose:&nbsp;&nbsp;一个动态链接库头文件示例<br/>*tided by: zhoulifa(zhoulifa@163.com) 周立发 (http://zhoulifa.9999mb.com)<br/>Linux 爱好者 Linux 知识传播者 SOHO 族 开发者 最擅长 C 语言<br/>*date time: 2006-11-15 21:11:54<br/>*Note: 任何人可以任意复制代码并运用这些文档，当然包括你的商业用途<br/>* 但请遵循 GPL<br/>*Hope:希望越来越多的人贡献自己的力量，为科学技术发展出力<br/>* 科技站在巨人的肩膀上进步更快！感谢有开源前辈的贡献！<br/>*感谢 vcclass@hotmail.com 提供原始代码，<br/><br/>我在他的基础上整理了此文<br/>*********************************************************************/<br/>int get ();<br/>int set (int a);</div><br/><br/>然后准备这样一个生成动态链接库的源文件：<br/>CODE:<br/><div class="code"><br/>/************关于本文档********************************************<br/>*filename:&nbsp;&nbsp;get.cpp<br/>*purpose: 一个动态链接库源文件示例<br/>*tided by: zhoulifa(zhoulifa@163.com) 周立发 (http://zhoulifa.9999mb.com)<br/>Linux 爱好者 Linux 知识传播者 SOHO 族 开发者 最擅长 C 语言<br/>*date time:2006-11-15 21:11:54<br/>*Note: 任何人可以任意复制代码并运用这些文档，当然包括你的商业用途<br/>* 但请遵循 GPL<br/>*Hope:希望越来越多的人贡献自己的力量，为科学技术发展出力<br/>* 科技站在巨人的肩膀上进步更快！感谢有开源前辈的贡献！<br/>*感谢 vcclass@hotmail.com 提供原始代码，<br/><br/>我在他的基础上整理了此文<br/>*********************************************************************/<br/>#include &lt;stdio.h&gt;<br/><br/>#include &quot;get.h&quot;<br/><br/> <br/><br/>static int x=0;<br/><br/>int get ()<br/><br/>&#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;get x=%d&#92;n&quot;, x);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return x;<br/><br/>&#125;<br/><br/>int set (int a)<br/><br/>&#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;set a=%d&#92;n&quot;, a);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x = a;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return x;<br/><br/>&#125;</div><br/>然后我们用 GNU 的 C/C++ 编译器来生成动态链接库，编译命令如下：<br/>QUOTE:<br/><div class="code">g++ get.cpp -shared -g -DDEBUG -o libggg.so</div><br/>实践发现会报错，<br/>/usr/bin/ld: /tmp/ccYLWPaw.o: relocation R_X86_64_32 against `.rodata&#039; can not be used when making a shared object; recompile with -fPIC<br/>实践成功命令如下：<br/>g++ get.cpp -shared -g -DDEBUG -o libggg.so -fPIC<br/><br/><br/><br/>这样我们就准备好了动态链接库了，下面我们编写一个应用程序来调用此动态链接库，源代码如下：<br/>CODE:<br/><div class="code"><br/>/************关于本文档********************************************<br/>*filename: pk.cpp<br/>*purpose: 一个调用动态链接库的示例<br/>*tided by: zhoulifa(zhoulifa@163.com) 周立发 (http://zhoulifa.9999mb.com)<br/>Linux 爱好者 Linux 知识传播者 SOHO 族 开发者 最擅长 C 语言<br/>*date time:2006-11-15 21:11:54<br/>*Note: 任何人可以任意复制代码并运用这些文档，当然包括你的商业用途<br/>* 但请遵循 GPL<br/>*Hope:希望越来越多的人贡献自己的力量，为科学技术发展出力<br/>* 科技站在巨人的肩膀上进步更快！感谢有开源前辈的贡献！<br/>*感谢 vcclass@hotmail.com 提供原始代码，<br/><br/>我在他的基础上整理了此文<br/>*********************************************************************/<br/>#include &lt;stdio.h&gt;<br/><br/>#include &quot;get.h&quot;<br/><br/>int main (int argc, char** argv)<br/><br/>&#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a = 100;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b = get ();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int c = set (a);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int d = get ();<br/><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;a=%d,b=%d,c=%d,d=%d&#92;n&quot;,a,b,c,d);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/><br/>&#125;</div><br/>编译此程序用下列命令，如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录，比如 /lib 或 /usr/lib 之类的，就用下面这条命令：<br/>CentOS64位的lib目录在：/usr/lib64/ ，得：cp -rf libggg.so /usr/lib64/.<br/>QUOTE:<br/><div class="code">g++ pk.cpp -o app -Wall -g -lggg</div><br/>否则就用下面这条命令：<br/>QUOTE:<br/><div class="code">g++ pk.cpp -o app -Wall -g -lggg -L`pwd`</div><br/><br/>下面我们就开始调试上面命令生成的 app 程序吧。如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录，比如 /lib或 /usr/lib 之类的，调试就顺利完成，如下：<br/><br/>QUOTE:<br/><div class="code"><br/>linux#gdb&quot;&gt;zhoulifa@linux#gdb ./app<br/>GNU gdb 6.4-debian<br/>Copyright 2005 Free Software Foundation,Inc.<br/>GDB is free software, covered by the GNU<br/><br/>General Public License, and you are<br/>welcome to change it and/or distribute<br/><br/>copies of it under certain conditions.<br/>Type &quot;show copying&quot; to see theconditions.<br/><br/><br/>There is absolutely no warranty for GDB.<br/><br/>Type &quot;show warranty&quot; for details.This GDB was configured as &quot;i486-linux-<br/><br/>gnu&quot;...Using host libthread_db library&quot;/lib/tls/i686/cmov/libthread_db.so.1&quot;.<br/><br/>(gdb) b main&nbsp;&nbsp;&nbsp;&nbsp;/* 这是在程序的 main 处设置断点 */<br/>Breakpoint 1 at 0x804853c: file pk.cpp,line 7.<br/>(gdb) b set&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 这是在程序的 set 处设置断点 */<br/>Function &quot;set&quot; not defined.<br/>Make breakpoint pending on future shared<br/><br/>library load? (y or &#91;n&#93;) y /* 这里必须选择 y 调试程序才会跟踪到动态链接库内部去<br/><br/>*/Breakpoint 2 (set) pending.<br/>(gdb) run /* 开始运行我们的程序，直到遇见断点时暂停 */<br/>Starting program: /data/example/c/app<br/>Breakpoint 3 at 0xb7f665f8: file get.cpp,line 11.<br/>Pending breakpoint &quot;set&quot; resolved<br/><br/>Breakpoint 1, main (argc=1,argv=0xbf990504) at pk.cpp:7<br/>7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a = 100;<br/>(gdb) n&nbsp;&nbsp;&nbsp;&nbsp; /* 继续执行程序的下一行代码<br/><br/>*/<br/>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int b = get ();<br/>(gdb) n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 程序执行到了我们断点所在的动态链接库了 */<br/>get x=0<br/>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int c = set (a);(gdb) n<br/><br/>Breakpoint 3, set (a=100) at get.cpp:11<br/>11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;set a=%d&#92;n&quot;, a);<br/><br/>(gdb) list&nbsp;&nbsp; /* 查看当前代码行周围的代码，证明我们已经跟踪到动态链接库的源代码里面了 */<br/>6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf (&quot;get x=%d&#92;n&quot;, x);<br/>7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x;<br/>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int set (int a)<br/>10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;set a=%d&#92;n&quot;, a);<br/>12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x = a;<br/>13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return x;<br/>14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>(gdb) n<br/>set a=100<br/>12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x = a;(gdb) n<br/>13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return x;(gdb) n<br/>14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>(gdb) n<br/>main (argc=1, argv=0xbf990504) at<br/><br/>pk.cpp:10<br/>10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int d = get ();<br/>(gdb) n<br/>get x=100<br/>11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;a=%d,b=%d,c=%<br/><br/>d,d=%d&#92;n&quot;,a,b,c,d);<br/>(gdb) n<br/>a=100,b=0,c=100,d=100<br/>12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>(gdb) c<br/>Continuing.<br/><br/>Program exited normally.<br/>(gdb) quit&nbsp;&nbsp;/* 程序顺利执行结束 */zhoulifa@linux#</div><br/>如果我们没有把动态链接库放到指定目录，比如/lib里面，调试就会失败，过程如下：<br/><br/>QUOTE:<br/><div class="code"><br/>zhoulifa@linux# gdb ./app<br/>GNU gdb 6.4-debian<br/>Copyright 2005 Free Software Foundation,<br/><br/>Inc.<br/>GDB is free software, covered by the GNU<br/><br/>General Public License, and you arewelcome to change it and/or distribute<br/><br/>copies of it under certain conditions.<br/><br/><br/>Type &quot;show copying&quot; to see theconditions.<br/>There is absolutely no warranty for GDB.<br/><br/>Type &quot;show warranty&quot; for details.<br/>This GDB was configured as &quot;i486-linux-<br/><br/>gnu&quot;...Using host libthread_db library<br/><br/>&quot;/lib/tls/i686/cmov/libthread_db.so.1&quot;.<br/><br/>(gdb) b main<br/>Breakpoint 1 at 0x804853c: file pk.cpp,<br/><br/>line 7.<br/>(gdb) b set<br/>Function &quot;set&quot; not defined.<br/>Make breakpoint pending on future shared<br/><br/>library load? (y or &#91;n&#93;) y<br/>Breakpoint 2 (set) pending.<br/>(gdb) run&nbsp;&nbsp;/* 虽然调试操作都一样，但程序执行失败 */<br/>Starting program: /data/example/c/app<br/>/data/example/c/app: error while loading<br/><br/>shared libraries: libggg.so: cannot open<br/><br/>shared object file: No such file or<br/><br/>directory<br/><br/>Program exited with code 0177.<br/>(gdb) quit<br/>zhoulifa@linux#</div>本次实验的环境是：<br/>CPU:AMD Athlon(tm) 64 Processor 3000+<br/>内存：512M<br/>OS:Ubuntu GNU/Linux 6.06 dapper LTS<br/>gcc:gcc 版本 4.0.3 (Ubuntu 4.0.3-1ubuntu5)<br/><br/>Linux下使用动态链接库<br/><br/>使用动态链接库，我认为，再比较大的程序运行过程中，是一种很有优势的。所以就花了一天时间来学习一下。<br/><br/>使用动态链接库，需要了解一下内容<br/><br/>头文件：<br/><div class="code"><br/> &lt;dlfcn.h&gt;<br/>函数：<br/>void *dlopen(const char *filename, int flag);<br/>const char *dlerror(void);<br/>void *dlsym(void *handle, char *symbol);<br/>int dlclose(void *handle);</div><br/><br/>相关的信息可以通过 man dlopen查询<br/><br/>在编译动生成态链接库的时候，<br/>需要参数 -shared<br/><br/>在使用动态链接库的时候，<br/>需要参数 -ldl<br/><br/>其他相关参数有<br/>-fpic -fPIC&nbsp;&nbsp;-rdynamic<br/><br/>如有库函数文件Lib.c， 主函数文件Main.c<br/>则有如下Makefile<br/><br/><br/><div class="code">all: comple link<br/><br/>comple:<br/>&nbsp;&nbsp;&nbsp;&nbsp;gcc -c Lib.c -o Lib.o<br/>&nbsp;&nbsp;&nbsp;&nbsp;gcc -c Main.c -o Main.o<br/><br/>link:<br/>&nbsp;&nbsp;&nbsp;&nbsp;gcc -shared Lib.o -o Lib.so<br/>&nbsp;&nbsp;&nbsp;&nbsp;gcc -ldl Main.o -o Main</div><br/><br/><br/>另外，在C++中使用动态连接库的时候，请注意：<br/>必须用<br/><div class="code">extern &quot;C&quot;<br/>&#123;<br/>&#125;</div>将动态苦定义为C的编译连接方式<br/><br/>否则由于C++命名方式于C不同，会造成生成的动态链接库不能使用（无法定位或函数）<br/><br/>文章选取的例子非常简单，上手容易，只是为了讲述静态与动态链接库的生成和链接过<br/>&nbsp;&nbsp;&nbsp;&nbsp;程，还有他们之间的区别。以下例子在 gcc 4.1.1 下顺利通过。<br/><br/><br/>文件预览 （补充）<br/>文件目录树如下，如你所见，非常简单。<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. libtest/&nbsp;&nbsp;<br/>&nbsp;&nbsp; 2. &#124;-- lt.c&nbsp;&nbsp;<br/>&nbsp;&nbsp; 3. &#124;-- lt.h&nbsp;&nbsp;<br/>&nbsp;&nbsp; 4. `-- test.c&nbsp;&nbsp;</div><br/><br/><br/><br/>代码<br/><br/><div class="code">#lt.c<br/><br/>&nbsp;&nbsp; 1. /* lt.c <br/>&nbsp;&nbsp; 2.&nbsp;&nbsp;* <br/>&nbsp;&nbsp; 3.&nbsp;&nbsp;*/&nbsp;&nbsp;<br/>&nbsp;&nbsp; 4.&nbsp;&nbsp; <br/>&nbsp;&nbsp; 5. #include &lt;stdio.h&gt;&nbsp;&nbsp;<br/>&nbsp;&nbsp; 6.&nbsp;&nbsp; <br/>&nbsp;&nbsp; 7. void myprint(void)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 8. &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp; 9.&nbsp;&nbsp; printf(&quot;Linux library test!&#92;n&quot;);&nbsp;&nbsp;<br/>&nbsp;&nbsp;10. &#125;&nbsp;&nbsp;</div><br/><br/><br/><div class="code"># lt.h<br/><br/>&nbsp;&nbsp; 1. /* lt.h <br/>&nbsp;&nbsp; 2.&nbsp;&nbsp;*&nbsp;&nbsp;<br/>&nbsp;&nbsp; 3.&nbsp;&nbsp;*/&nbsp;&nbsp;<br/>&nbsp;&nbsp; 4.&nbsp;&nbsp; <br/>&nbsp;&nbsp; 5. void myprint(void);&nbsp;&nbsp;</div><br/><br/><br/><br/><br/><div class="code">#test.c<br/><br/>&nbsp;&nbsp; 1. /* test.c <br/>&nbsp;&nbsp; 2.&nbsp;&nbsp;* <br/>&nbsp;&nbsp; 3.&nbsp;&nbsp;*/&nbsp;&nbsp;<br/>&nbsp;&nbsp; 4.&nbsp;&nbsp; <br/>&nbsp;&nbsp; 5. #include &quot;lt.h&quot;&nbsp;&nbsp;<br/>&nbsp;&nbsp; 6.&nbsp;&nbsp; <br/>&nbsp;&nbsp; 7. int main(void)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 8. &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp; 9.&nbsp;&nbsp; myprint();&nbsp;&nbsp;<br/>&nbsp;&nbsp;10.&nbsp;&nbsp; return 0;&nbsp;&nbsp;<br/>&nbsp;&nbsp;11. &#125;&nbsp;&nbsp;</div><br/><br/>先看静态库<br/>首先做成静态库 liblt.a 。<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ gcc -c lt.c -o lt.o&nbsp;&nbsp;<br/>&nbsp;&nbsp; 2. $ ar cqs liblt.a lt.o&nbsp;&nbsp;</div><br/><br/><br/><br/><br/>再者，链接，这里指定了静态库的位置，注意文件顺序不可乱序。<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ gcc test.o liblt.a -o test&nbsp;&nbsp;</div><br/><br/><br/><br/>这个时候再来看他的引用库情况。<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ ldd test&nbsp;&nbsp;<br/>&nbsp;&nbsp; 2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; linux-gate.so.1 =&gt;&nbsp;&nbsp;(0xffffe000)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; libc.so.6 =&gt; /lib/libc.so.6 (0xb7e29000)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /lib/ld-linux.so.2 (0xb7f6e000)&nbsp;&nbsp;</div><br/><br/><br/><br/>动态库<br/>做成动态库 liblt.so 。<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ gcc -c lt.c -o lt.o&nbsp;&nbsp;<br/>&nbsp;&nbsp; 2. $ gcc -shared -Wall -fPIC lt.o -o liblt.so&nbsp;&nbsp;</div><br/><br/><br/><br/>链接方法I，拷贝到系统库里再链接，让gcc自己查找<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ sudo cp liblt.so /usr/lib&nbsp;&nbsp;<br/>&nbsp;&nbsp; 2. $ gcc -o test test.o -llt&nbsp;&nbsp;</div><br/><br/><br/>这里我们可以看到了 -llt 选项，-l[lib_name] 指定库名，他会主动搜索<br/>lib[lib_name].so 。这个搜索的路径可以通过 gcc --print-search-dirs来查找。<br/><br/>链接方法II，手动指定库路径<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ cc -o test test.o -llt -B /path/to/lib</div><br/><br/><br/>这里的-B 选项就添加 /path/to/lib 到gcc搜索的路径之中。这样链接没有问题但是方法II<br/>中手动链接好的程序在执行时候仍旧需要指定库路径（链接和执行是分开的）。需要添加系<br/>统变量 LD_LIBRARY_PATH :<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ export LD_LIBRARY_PATH=/path/to/lib&nbsp;&nbsp;</div><br/><br/><br/><br/>这个时候再来检测一下test程序的库链接状况(方法I情况)<br/><br/><br/><div class="code">&nbsp;&nbsp; 1. $ ldd test&nbsp;&nbsp;<br/>&nbsp;&nbsp; 2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; linux-gate.so.1 =&gt;&nbsp;&nbsp;(0xffffe000)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; liblt.so =&gt; /usr/lib/liblt.so (0xb7f58000)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; libc.so.6 =&gt; /lib/libc.so.6 (0xb7e28000)&nbsp;&nbsp;<br/>&nbsp;&nbsp; 5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /lib/ld-linux.so.2 (0xb7f6f000)&nbsp;&nbsp;</div><br/><br/><br/>恩，是不是比静态链接的程序多了一个 liblt.so ？恩，这就是静态与动态的最大区别，静<br/>态情况下，他把库直接加载到程序里，而在动态链接的时候，他只是保留接口，将动态库与<br/>程序代码独立。这样就可以提高代码的可复用度，和降低程序的耦合度。<br/><br/><br/><br/><br/><div class="code">&#91;xiangdong2@vm19 so2&#93;$ export LD_LIBRARY_PATH=&quot;&quot;<br/>&#91;xiangdong2@vm19 so2&#93;$ ./app <br/>./app: error while loading shared libraries: libggg.so: cannot open shared object file: No such file or directory<br/>&#91;xiangdong2@vm19 so2&#93;$ export LD_LIBRARY_PATH=/home/xiangdong2/so2/pwd<br/>&#91;xiangdong2@vm19 so2&#93;$ ./app <br/>get x=0<br/>set a=100<br/>get x=100<br/>a=100,b=0,c=100,d=100<br/>&#91;xiangdong2@vm19 so2&#93;$ export LD_LIBRARY_PATH=/home/xiangdong2/so2/pwd2<br/>&#91;xiangdong2@vm19 so2&#93;$ ./app <br/>./app: error while loading shared libraries: libggg.so: cannot open shared object file: No such file or directory</div>
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [实践OK]Linux 动态链接库编程基础，以及生成的动态链接库里的函数和地址查看之nm -D  /usr/local/php/lib/php/extensions/no-debug-non-zts-20180731/memcache.so ]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>