热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux的动态库文件和静态库文件

lib文件一般来说,库文件有两种:动态库和静态库。1.动态库动态库(也叫共用库)是编译好的代码片段,在程序执行时由运行时连接文件(runtimelinker)libld.so加载。这有

lib文件
一般来说,库文件有两种:动态库和静态库。
1.动态库
动态库(也叫共用库)是编译好的代码片段,在程序执行时由运行时连接文件(runtime linker)/lib/ld.so加载。这有点类似于windows下的dll文件。在提高效率方面,这样做可以节省系统在以下方面的开销:
硬件设备:不同的程序可以共享相同的代码。
内存:内核可以将库文件的拷贝存放在内存里以便进程之间共享。
时间:只要你不再重新编译库文件,重新生成可执行文件只需处理更少的代码。
习惯上,动态库以字符串so命名,后面加上版本号。例如:
libc.so.6 C语言的库文件.千万别给删掉了:)
libcrypt.so.1 影子口令系统的编码库.
libncurses.so.4.2 The new curses library routines.

2.静态库
静态库在编译的时候被固定在了可执行文件中,而不是放在系统的某个地方由ld.so加载。这种做法好的一面是可执行文件自己包含了所需的所有库文件,并不依赖于系统中的其他代码,也不会出现库文件缺失的情况。你可以把这些代码复制给任何人,而它们保证可以工作。不好的一面就是可执行文件不必要的增大了,而且不同的程序之间不能共享代码。
习惯上,我们以后缀.a来标记静态库文件。例如:
libgtk.a GIMP和其他X应用的图形库.
libcrypt.a 影子口令系统的编码库.
libvga.a. [S]VGA图形库.

3.静态库与动态库的对比
使用静态库的程序要比使用动态库的程序稍微快一些。我曾见过有人说两者之间启动时间的相差5%的数量级。但是,别忘了,动态库的好处之一是建立在一种假定条件下,即这些可执行代码已经被加载到了内存中.事实上,对于像libc这样的库文件,确实是一直保存在内存中的。如果你要运行一个使用静态库编译的 netscape,必然要多等上一点时间。因此,对于“哪种库文件更快”这个问题的答案应该是“看情况而定”。但是一般来说,用动态库编译的的程序要更快一些,因为大部分情况下你所需要的库都已经加载到内存中了。


4.重要的文件/可执行文件
这个程序/lib/ls.so负责为可执行文件连接动态库。它在下面的文件夹里搜索库文件:
环境变量LD_LIBRARY_PATH中列出的目录,除非该程序设定了sid或者uid,以跳过环境变量。
文件/etc/ld.so.cache中列出的目录。
In /usr/lib
In /lib
至于为什么ld.so不去搜索/usr/local/lib,自有它的理由,我可以告诉你,但那会折磨死你。有些东西根本就不是要凡人知道的...
在/etc/ld.so.cache这个文件中包含了一个需要搜索的目录的汇总列表和一个备用库文件的列表。这个文件(/etc/ld.so.cache)是由/sbin/ldconfig创建的。
/sbin/ldconfig在系统启动时自动运行,也可在编译完成库文件后手动运行(每次安装软件之后都手动运行该文件是个不错的习惯)。 ldconfig生成/etc/ld.so.cache文件,它搜索/lib、/usr/lib以及其他在/etc/ld.so.conf中列出的需要搜索的目录。

在配置文件/etc/ld.so.conf中列出了所有ldconfig需要搜索以生成ld.so.cache文件的目录。

如果你把库文件放在了不是默认的文件夹里(比如/home/lib),你应该把这个目录手工添加到/etc/ld.so.conf里,然后重新运行/sbin/ldconfig。

注:上面的方法是提供了如何添加自定义的或者新安装的软件的库文件路径


5.非常有用的工具
许多程序都要求你的系统中存在某些动态库以便运行时调用,你如何才能找出哪些动态库是某个程序所需要的呢?这里有两种方法【strace 和 ldd】。
你可以使用strace,例如,先在终端下面用locate命令找出你系统里的xmms,xcalc或者xpaint所在的位置,然后运行以下命令:
strace -o LOG /usr/X11R6/bin/xcalc
关闭程序之后你会发现一个叫LOG的文件留了下来。用文本编辑器打开LOG,查找字符串so。你能看到哪些库文件被xcalc调用,还有上面提到的几个文件比如ld.so.cache或者libc.so。你或许还能看到一些有趣的东西,比如当在一个目录中没有找到某一个库,返回“file not found”,程序会到另一个目录继续搜索该库。就像下面这样:
open("/usr/local/rvplayer5.0/libXext.so.6", O_RDONLY) = -1 ENOENT (No such
file or directory)
open("/usr/X11R6/lib/libXext.so.6", O_RDONLY) = 4
很明显,libXext.so.6不在/usr/local/rvplayer5.0中,但是随后ld.so在/usr/X11R6/lib中找到了它。幸运的是,还有一种获取这些信息的更方便的方法:
ldd /usr/X11R6/bin/xcalc (必须使用完整的路径)
ldd将会返回如下信息:
libXaw.so.6 => /usr/X11R6/lib/Xaw3d/libXaw.so.6 (0x40020000)
libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0x40077000)
libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x40089000)
libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x400d3000)
libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x400dd000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x400f3000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x400ff000)
libm.so.6 => /lib/libm.so.6 (0x401a5000)
libc.so.6 => /usr/lib/libc.so.6 (0x401c2000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

呵呵,它甚至把库文件所在的位置都给你找了出来!用着很舒服吧?
6.结束语
当你准备写一个“helloworld”那样的小程序然后用gcc编译时,用的是动态库还是静态库呢?除非你给连接器-static选项,gcc使用的是动态库。例如,这是我的演示程序:
% cat try.c

#include
int main(void) {
printf("Hello, world!\n");
return 0; }

用gcc编译:
% gcc try.c

下面就是ldd大显身手了:
% ldd a.out

libc.so.6 => /usr/lib/libc.so.6 (0x40020000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

现在我们使用静态库编译:
% gcc -static try.c

再用ldd分析这个新的可执行文件:
% ldd a.out
not a dynamic executable

看到了吗?这就是理论的实际运用!


推荐阅读
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • Java中提取字符串的最后一部分
    本文介绍了如何使用Java中的substring()和split()方法来提取字符串的最后一部分,特别是在处理包含特殊字符的路径时的方法与技巧。 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • C/C++ 应用程序的安装与卸载解决方案
    本文介绍了如何使用Inno Setup来创建C/C++应用程序的安装程序,包括自动检测并安装所需的运行库,确保应用能够顺利安装和卸载。 ... [详细]
  • 在使用 PyInstaller 将 Python 应用程序打包成独立的可执行文件时,若项目中包含动态加载的库或插件,需要正确配置 --hidden-import 和 --add-binary 参数,以确保所有依赖项均能被正确识别和打包。 ... [详细]
  • 想把一组chara[4096]的数组拷贝到shortb[6][256]中,尝试过用循环移位的方式,还用中间变量shortc[2048]的方式。得出的结论:1.移位方式效率最低2. ... [详细]
  • 本文详细介绍了Linux系统中信号量的相关函数,包括sem_init、sem_wait、sem_post和sem_destroy,解释了它们的功能和使用方法,并提供了示例代码。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 实现Win10与Linux服务器的SSH无密码登录
    本文介绍了如何在Windows 10环境下使用Git工具,通过配置SSH密钥对,实现与Linux服务器的无密码登录。主要步骤包括生成本地公钥、上传至服务器以及配置服务器端的信任关系。 ... [详细]
  • 本文介绍了如何使用 Python 的 Pyglet 库加载并显示图像。Pyglet 是一个用于开发图形用户界面应用的强大工具,特别适用于游戏和多媒体项目。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • Eclipse 开发环境配置指南:从下载到免安装配置
    Eclipse 是一个广泛使用的开源Java开发环境,掌握其正确的安装与配置方法对于初学者至关重要。本文将详细介绍如何下载、安装及配置Eclipse,确保您的开发环境搭建顺利。 ... [详细]
  • 【MySQL】frm文件解析
    官网说明:http:dev.mysql.comdocinternalsenfrm-file-format.htmlfrm是MySQL表结构定义文件,通常frm文件是不会损坏的,但是如果 ... [详细]
  • Awk是一款功能强大的文本分析与处理工具,尤其在数据解析和报告生成方面表现突出。它通过读取由换行符分隔的记录,并按照指定的字段分隔符来划分和处理这些记录,从而实现复杂的数据操作。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
author-avatar
潜伏在人间_144
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有