- 浏览: 4820589 次
- 性别:
- 来自: 上海
博客专栏
-
robbin谈管理
浏览量:137002
文章分类
最新评论
-
xly1981:
领导者是团队的灵魂。深入一线的过程,包括代码review,能帮 ...
robbin谈管理:改造团队的经验(2) -
jiehuangwei:
像这种总结比较性的ppt文档可以多发啊
Web并发模型粗浅探讨 -
linux1308:
看完学习到了很多东西,感谢推荐!
推荐一篇很好的RoR部署方案性能评测 -
zweite:
直接对搜索的结果进行缓存是不是会更快一点呢
漫谈应用缓存的命中率问题 -
kaogua:
现在已经是ruby2.0了, 不知道这个的效率是怎么样的, 是 ...
Ruby作为服务器端应用已经成熟了
对大多数不从事Linux平台C语言开发的人来说,GNU gcc的一套工具和Linux平台的共享库的使用还是十分陌生的,其实我也不太熟悉,姑且写点基础知识,权当做备忘吧。
一、GNU gcc的编译工具用法
我们先来写一个简单的C程序:hello.c
定义了一个print_hello函数,调用main函数打印Hello World。
如何编译它呢?
-o参数指定生成的可执行程序的文件名, -O2是优化级别。该命令会编译生成hello可执行程序,看看这个文件:ls -l hello
有11KB大小。
看看他链接了哪些系统动态链接库,用ldd命令:
输出信息为:
libc是C语言标准函数库,ld是动态链接器。
接着我们看看hello这个程序里面有哪些符号,用nm命令:
输出:
中间省略了一些,不过我们还是可以在符号表里面找到函数定义。
hello有11KB,体积偏大,去处符号表可以给它瘦身,我们用strip命令:
然后再ls -l hello,输出为:
只有4.4KB了,瘦身效果明显! 不过这次符号表再也看不到了,nm hello,输出为:nm: hello: no symbols。
最后如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令:
输出信息为:
友情提醒一下,如果你用Java写一个HelloWorld.java,编译以后你也可以用strings窥探一番。
二、动态共享库怎么使用
这次我们把hello.c拆开成为两个文件:hello.c和main.c。hello.c的代码是:
而main.c的代码是:
hello.c是我们的动态共享库,在hello.c里面我们声明和实现了各种公用的函数,最后main.c可以去调用这些公用函数。首先我们要把hello.c编译成为动态共享库:
-fPIC参数声明链接库的代码段是可以共享的,-shared参数声明编译为共享库。请注意这次我们编译的共享库的名字叫做libhello.so,这也是Linux共享库的一个命名的惯例了:后缀使用so,而名称使用libxxxx格式。
然后编译main.c的时候,我们需要更多的参数让gcc知道如何寻找共享库:
-L参数指定到哪个附加路径下面去寻找共享库,现在我们指定在当前目录下面寻找;
-l参数指定链接到哪个共享库上面,我们传的参数hello,那么gcc就会自动链接到libhello.so这个共享库上面(注意我们上面说的libXXXX.so命名规则);
-I参数指定到哪个附加路径下面去寻找h文件,这个我们没有使用。
最后我们成功编译好了main,执行一下,报错:
找不到libhello.so这个共享库,怎么回事?这是因为libhello.so并不在操作系统默认的共享库的路径下面,我们可以临时指定一下链接路径:
这样就成功了。我们用ldd main看一下:
这次main程序链接到了libhello.so这个共享库上面。
三、关于Linux的动态共享库的设置
可执行程序找不到要链接的动态共享库,这是Linux上面编译和运行程序很容易碰到的问题,通过上面的小例子,我们已经大致了解共享库的一点基本原理,接下来我们要探讨一下怎么设置程序寻找动态共享库的行为。
Linux操作系统上面的动态共享库大致分为三类:
1、操作系统级别的共享库和基础的系统工具库
比方说libc.so, libz.so, libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr/lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6/lib64目录。此外还可能有其他特定Linux版本的系统库目录。
这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。
2、应用程序级别的系统共享库
并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local/lib下面去寻找共享库。
以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢? 因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大致如下:
假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用ImageMagick的动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig 命令即可。
ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:
输出结果为:
已经成功了!
3、应用程序独享的动态共享库
有很多共享库只被特定的应用程序使用,那么就没有必要加入系统库路径,以免应用程序的共享库之间发生版本冲突。因此Linux还可以通过设置环境变量LD_LIBRARY_PATH来临时指定应用程序的共享库搜索路径,就像我们上面举的那个例子一样,我们可以在应用程序的启动脚本里面预先设置LD_LIBRARY_PATH,指定本应用程序附加的共享库搜索路径,从而让应用程序找到它。
友情提示:表乱用strip 不然等你的应用dumpcore的时候就很难gdb了
strip之后还能gdb?不能把
windows 下会生成一个默认的 DllMain 吧?
一、GNU gcc的编译工具用法
我们先来写一个简单的C程序:hello.c
#include <stdio.h> void print_hello() { printf("Hello World\n"); } int main(int argc, char argv[]) { print_hello(); return 0; }
定义了一个print_hello函数,调用main函数打印Hello World。
如何编译它呢?
gcc -o hello -O2 hello.c
-o参数指定生成的可执行程序的文件名, -O2是优化级别。该命令会编译生成hello可执行程序,看看这个文件:ls -l hello
-rwxr-xr-x 1 robbin users 11939 2008-11-02 13:48 hello
有11KB大小。
看看他链接了哪些系统动态链接库,用ldd命令:
ldd hello
输出信息为:
libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9566d000) /lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)
libc是C语言标准函数库,ld是动态链接器。
接着我们看看hello这个程序里面有哪些符号,用nm命令:
nm hello
输出:
00000000005008f8 A __bss_start 000000000040043c t call_gmon_start ...... 00000000004004f0 T main 0000000000500658 d p.0 00000000004004e0 T print_hello U puts@@GLIBC_2.2.5 0000000000400410 T _start
中间省略了一些,不过我们还是可以在符号表里面找到函数定义。
hello有11KB,体积偏大,去处符号表可以给它瘦身,我们用strip命令:
strip hello
然后再ls -l hello,输出为:
-rwxr-xr-x 1 webuser users 4464 2008-11-02 13:56 hello
只有4.4KB了,瘦身效果明显! 不过这次符号表再也看不到了,nm hello,输出为:nm: hello: no symbols。
最后如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令:
strings hello
输出信息为:
/lib64/ld-linux-x86-64.so.2 SuSE libc.so.6 puts __libc_start_main __gmon_start__ GLIBC_2.2.5 t fff Hello World
友情提醒一下,如果你用Java写一个HelloWorld.java,编译以后你也可以用strings窥探一番。
二、动态共享库怎么使用
这次我们把hello.c拆开成为两个文件:hello.c和main.c。hello.c的代码是:
#include <stdio.h> void print_hello() { printf("Hello World\n"); }
而main.c的代码是:
int main(int argc, char argv[]) { print_hello(); return 0; }
hello.c是我们的动态共享库,在hello.c里面我们声明和实现了各种公用的函数,最后main.c可以去调用这些公用函数。首先我们要把hello.c编译成为动态共享库:
gcc -o libhello.so -O2 -fPIC -shared hello.c
-fPIC参数声明链接库的代码段是可以共享的,-shared参数声明编译为共享库。请注意这次我们编译的共享库的名字叫做libhello.so,这也是Linux共享库的一个命名的惯例了:后缀使用so,而名称使用libxxxx格式。
然后编译main.c的时候,我们需要更多的参数让gcc知道如何寻找共享库:
gcc -o main -O2 -L. -lhello main.c
-L参数指定到哪个附加路径下面去寻找共享库,现在我们指定在当前目录下面寻找;
-l参数指定链接到哪个共享库上面,我们传的参数hello,那么gcc就会自动链接到libhello.so这个共享库上面(注意我们上面说的libXXXX.so命名规则);
-I参数指定到哪个附加路径下面去寻找h文件,这个我们没有使用。
最后我们成功编译好了main,执行一下,报错:
引用
./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
找不到libhello.so这个共享库,怎么回事?这是因为libhello.so并不在操作系统默认的共享库的路径下面,我们可以临时指定一下链接路径:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
这样就成功了。我们用ldd main看一下:
libhello.so => ./libhello.so (0x0000002a9566d000) libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9576e000) /lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)
这次main程序链接到了libhello.so这个共享库上面。
三、关于Linux的动态共享库的设置
可执行程序找不到要链接的动态共享库,这是Linux上面编译和运行程序很容易碰到的问题,通过上面的小例子,我们已经大致了解共享库的一点基本原理,接下来我们要探讨一下怎么设置程序寻找动态共享库的行为。
Linux操作系统上面的动态共享库大致分为三类:
1、操作系统级别的共享库和基础的系统工具库
比方说libc.so, libz.so, libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr/lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6/lib64目录。此外还可能有其他特定Linux版本的系统库目录。
这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。
2、应用程序级别的系统共享库
并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local/lib下面去寻找共享库。
以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢? 因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大致如下:
/usr/X11R6/lib64 /usr/X11R6/lib /usr/local/lib /lib64 /lib /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/ImageMagick/lib
假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用ImageMagick的动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig 命令即可。
ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:
strings /etc/ld.so.cache | grep ImageMagick
输出结果为:
/usr/local/ImageMagick/lib/libWand.so.10 /usr/local/ImageMagick/lib/libWand.so /usr/local/ImageMagick/lib/libMagick.so.10 /usr/local/ImageMagick/lib/libMagick.so /usr/local/ImageMagick/lib/libMagick++.so.10 /usr/local/ImageMagick/lib/libMagick++.so
已经成功了!
3、应用程序独享的动态共享库
有很多共享库只被特定的应用程序使用,那么就没有必要加入系统库路径,以免应用程序的共享库之间发生版本冲突。因此Linux还可以通过设置环境变量LD_LIBRARY_PATH来临时指定应用程序的共享库搜索路径,就像我们上面举的那个例子一样,我们可以在应用程序的启动脚本里面预先设置LD_LIBRARY_PATH,指定本应用程序附加的共享库搜索路径,从而让应用程序找到它。
评论
8 楼
Thorndike
2009-05-04
GCC在Linux环境,如果脱离Binutils和Glibc,有很多概念都不会理解透彻。
7 楼
zhangyafei_kimi
2009-05-03
seen 写道
友情提示:表乱用strip 不然等你的应用dumpcore的时候就很难gdb了
strip之后还能gdb?不能把
6 楼
night_stalker
2009-04-06
54powerman 写道
正在琢磨用gcc写供vb调用的dll,之前看很多资料说DllMain是必须的,今天搞了一个发现不需要。学习中。。。
收藏这篇。
收藏这篇。
windows 下会生成一个默认的 DllMain 吧?
5 楼
ray_linn
2009-04-06
LD_LIBRARY_PATH --不一定管用的,尤其是在交叉编译GCC的时候。
我都是用-O3 -fomit-frame-pointer,后者在x86是关闭的,要显式打开。
我都是用-O3 -fomit-frame-pointer,后者在x86是关闭的,要显式打开。
4 楼
agurick
2009-04-06
-fPIC 貌似是生成与位置无关代码吧。
3 楼
Omnibus
2008-11-21
初次編寫還是不要用-O2,用-g。萬一crash都可以用gdb debug。直至無問題才轉用-O2。
2 楼
54powerman
2008-11-20
正在琢磨用gcc写供vb调用的dll,之前看很多资料说DllMain是必须的,今天搞了一个发现不需要。学习中。。。
收藏这篇。
收藏这篇。
1 楼
seen
2008-11-02
友情提示:表乱用strip 不然等你的应用dumpcore的时候就很难gdb了
发表评论
-
Web并发模型粗浅探讨
2012-12-10 01:22 16906我带的研发部门使用的编程语言有Java,.net,PHP和Ru ... -
让textmate可以直接修改远程服务器上的文件
2012-11-06 17:20 54651. 在textmate的 Preferences | Ter ... -
晒晒我们的开源项目
2012-09-23 22:17 38422我们的研发团队是一支mini型研发团队,目前共有研发人员13人 ... -
再谈非主流工业语言
2011-03-22 00:15 23167今天看到Fenng同学的发 ... -
我的PHP,Python和Ruby之路
2011-03-21 12:12 72464因为看到一篇讨论PHP,P ... -
互联网网站的反爬虫策略浅析
2009-08-17 01:07 38205因为搜索引擎的流行, ... -
记上海Python社区聚会,谈Python和Ruby
2009-08-10 18:49 248808月9日周日,上海Python ... -
LVM - 很好很强大
2008-11-29 22:19 35903LVM (Logic Volume Management, ... -
贴一段遍历memcached缓存对象的小脚本
2008-10-13 18:07 13749memcached因为性能的缘故,没有提供遍历整个缓存当中对象 ... -
用Google的网站流量分析系统来看全球软件行业的分工趋势
2008-06-25 13:05 10483用Google的网站流量分析 ... -
memcache_engine + memcachedb = 高性能分布式内存数据库
2008-01-22 12:05 33884memcachedb是一个由新浪网 ... -
豆瓣的程序性能真的很惊人,但...
2008-01-17 22:42 34560http://www.dbanotes.net/arch/do ... -
关系模型和对象模型的究竟匹配还是不匹配?
2007-12-27 12:23 12809在过去的很多年,我以 ... -
AJAX与RIA技术之我见
2007-08-02 11:46 43412DHH于6月底曾经发表过一 ... -
从分布式系统的角度看REST
2007-05-23 15:46 51783上周末在杭州网侠大会 ... -
软件行业2006年终回顾以及2007展望(二)展望
2006-12-11 22:02 13070http://www.iteye.com/topic/1778 ... -
Linux reiserfs文件系统即将陨落
2006-10-12 16:29 25209Linux著名的高性能文件系统reiserfs向来是Linux ... -
lighttpd的tunning tips
2006-09-21 00:20 6759http://trac.lighttpd.net/trac/w ... -
动态脚本语言的部署运行方式介绍
2006-09-18 12:42 7831现在这类脚本语言的运行方式基本上有三种: 1、Apache ...
相关推荐
一、Linux 平台 gcc 和动态共享库的基础知识 1)GNU gcc 的编译工具用法 2)动态共享库怎么使用 3)关于 Linux 的动态共享库的设置 二、GCC——C 程序是如何编译成的 三、GCC 使用详解
本篇文章将深入探讨Linux环境下GCC的使用以及动态共享库的基础知识。 首先,GCC的工作流程可以分为预处理、编译、汇编和链接四个阶段。预处理阶段处理宏定义、条件编译指令和包含文件;编译阶段将源代码转换为汇编...
### Linux静态库及动态库创建及使用 #### 一、基本概念 ##### 1.1 什么是库 在计算机编程领域,**库**(Library)是一系列预编译的代码集合,这些代码通常...这些基础知识对于理解和使用Linux系统中的库非常有帮助。
本文旨在介绍Linux下动态库的基础知识及其使用方法。 **1.1 静态库与动态库的区别** - **静态库**: 在编译链接阶段,静态库中的代码会被复制到可执行文件中,成为可执行文件的一部分。这意味着使用静态库编译的...
### Linux静态库与动态库详解 #### 一、引言 在Linux环境下开发软件时,经常需要使用到库文件来实现复杂的功能。这些库文件可以分为两大类:...在实际开发中,了解这些基础知识对于提高开发效率和软件质量至关重要。
### Linux静态与动态链接库的创建及使用 #### 一、引言 在Linux系统中,库文件是...了解这些基础知识对于开发高质量的Linux应用程序至关重要。通过合理选择静态库或动态库,可以根据具体需求优化程序性能和资源利用。
### Linux系统下C语言编程基础知识详解 #### 一、源程序编译 在Linux环境下,进行C语言编程的首要步骤是源程序的编译。这一过程通常借助于GNU的GCC(GNU Compiler Collection)编译器完成。GCC不仅支持C语言,还...
Linux编程基础是一个涵盖广泛的主题,包括使用GCC编译器、GDB调试器、动态库的构建以及Makefile的编写。这些是Linux环境下软件开发的重要工具和技术。以下是对这些知识点的详细解释: 1. **GCC(GNU Compiler ...
`libstdc++.so.6.0.13`是`libstdc++`的一个具体版本,其中`.so`表示共享对象(Shared Object),在Linux中就是动态链接库。当程序运行时,如果没有找到所需的动态链接库,可以通过手动将库文件复制到系统库路径(如/...
【标题】:“gcc Linux”...以上内容涵盖了与“gcc Linux”相关的多个知识点,包括`gcc`的使用、Linux环境配置、虚拟机网络设置以及基础的Linux工具使用。了解和掌握这些内容对Linux系统的日常使用和开发工作至关重要。
在Linux环境下,动态库和静态库是软件开发中的两种常见库类型,它们在程序编译链接阶段扮演着重要角色。本文将深入解析动态库的建立过程,同时对比静态库,以帮助读者更好地理解和应用。 #### 静态库与动态库的区别...
一、C语言基础知识 1. C语言概述:C语言由Dennis Ritchie于1972年开发,是一种中级语言,结合了高级语言的可读性和低级语言的控制力。它的语法简洁,执行效率高,被广泛用于系统编程、嵌入式开发和软件开发等领域。 ...
接下来,我们详细介绍了链接库的基础知识。链接库文件是实现了特定功能的函数集合,分为静态链接库和动态链接库。静态库(如在Linux下以`.a`结尾的文件)在编译时会将库代码合并到可执行文件中,使得程序独立,但...
本文将围绕“Linux平台上学C语言”这个主题,详细讲解相关知识点,帮助初学者或有志于深入Linux环境下的C语言编程者。 首先,C语言是一种强大的、高效的编程语言,它的语法简洁明了,对于理解计算机工作原理和操作...
这个基础教程旨在帮助初学者快速入门Linux,通过学习这些基础知识,可以理解Linux系统的运作机制,并能够熟练地在终端进行日常操作。随着对Linux的深入理解,可以进一步探索更高级的主题,如系统管理、网络服务、...
本节将从Linux函数库开始,详细介绍Linux开发基础的知识点。 一、Linux函数库 Linux函数库是一个文件,包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他程序使用。函数库可以使整个程序更加...