1 背景

原来跑的好好的进程,重启后没跑多少就挂掉了,奇怪了。经过跟踪,原来是加载了一个.so文件,于是决定学习一下library相关的东东,现在和大家分享一下。

2 分类

C/C++ library可分为三类:静态库(Static Libraries)、共享库(shared Libraries)和动态加载库(dynamically loaded DL libraries)。

静态库在程序编译时会被连接到可执行程序中,程序运行时将不再需要该静态库。

共享库在程序编译时并不会被连接到可执行程序中,而是在可执行程序启动时被载入内存的,因此在程序运行时还需要动态库存在。

动态加载库在可执行程序执行的任何时候可以被加载。 DL libraries aren't really a different kind of library format (both static and shared libraries can be used as DL libraries)。

3 Static Libraries

创建方法:

ar rcs libmy_library.a file1.o file2.o

4 Shared Libraries

4.1 命名

soname: version number,由ldconfig -n $library_directory生成,程序加载依赖的名字,

library安装好之后,根据realname生成soname

realname: soname的基础上增加minor number和release number

linkername: 以so结尾,没有version number,也没有minor number和release number,

ldconfig对于开发程序时你要链接的library不做出任何假定,不会自动生成linkername

有如下的指向关系

soname -> realname

linkername -> realname

例子如下所示:

soname ----> /usr/lib/libreadline.so.3 -> /usr/lib/libreadline.so.3.0

realname ----> /usr/lib/libreadline.so.3.0

linkername ----> /usr/lib/libreadline.so -> /usr/lib/libreadline.so.3

所以一般的情况是

linkername -> soname -> realname

4.2 使用方法

当执行一个ELF文件的时候,program loader(/lib/ld-linux.so.X,程序加载器)寻找并加载ELF文件所需要的所有libraries,搜寻的目录在/etc/ld.so.conf当中指定。/etc/ld.so.preload 文件当中指示那些预加载的,优先级高于一般libraries的库,为了提高加载效率,不用每次执行一个程序都去搜索,便有了文件/etc/ld.so.cache,每次有新的libraries加入或者删除一些libraries,都应该运行ldconfig,更新文件/etc/ld.so.cache。

4.3 环境变量

4.3.1 LD_LIBRARY_PATH

LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径,注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径之前进行查找。设置方法如下(其中,LIBDIR1和LIBDIR2为两个库目录):

export LD_LIBRARY_PATH=LIBDIR1:LIBDIR2:$LD_LIBRARY_PATH

4.3.2 LIBRARY_PATH

LIBRARY_PATH环境变量用于在程序编译期间查找动态链接库时指定查找共享库的路径,例如,指定gcc编译需要用到的动态链接库的目录。设置方法如下(其中,LIBDIR1和LIBDIR2为两个库目录):

export LIBRARY_PATH=LIBDIR1:LIBDIR2:$LIBRARY_PATH

4.3.3 LD_PRELOAD

这个变量的作用类似于/etc/ld.so.preload

4.3.4 LD_DEBUG=files/libs/bindings/versions/help

通过这个变量的设置会显示share library函数调用时候的更加详细信息

4.4 工具

4.4.1 动态链接库管理命令ldconfig

为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig.

ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表。

ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令。

4.4.2 ldd

ldd,列出某个程序依赖的shared library,不要对某个不信任的程序进行ldd,因为ldd的工作方式是:首先,设置某个变量,LD_TRACE_LOADED_OBJECTS,然后,执行这个程序。

4.5 创建shared libraries

gcc -fPIC -g -c -Wall a.c

gcc -fPIC -g -c -Wall b.c

gcc -shared -Wl,-soname,libmystuff.so.1 \

-o libmystuff.so.1.0.1 a.o b.o -lc

-fPIC与-fpic比较,fPIC编译的文件比较大,和平台无关,fpic编译的比较小,和平台有关。不用使用-fomit-frame-pointer这个编译参数除非你不得不这样。虽然使用了这个参数获得的函数库仍然可以使用,但是这使得调试程序几乎 没有用,无法跟踪调试。需要使用“-Wl,-export-dynamic”这个选项参数。通常,动态函数库的符号表里面包含了这些动态的对象的符号。 这个选项在创建ELF格式的文件时候,会将所有的符号加入到动态符号表中。可以参考ld的帮助获得更详细的说明。如果在linux可以用``-rdynamic'' 代替``-Wl,export-dynamic''。

在开发过程中,想修改一个库,但该库也用于许多其他程序, 你不希望其他程序使用修改的库,只让一个特定的应用程序测试,一个链接选项:`rpath',它指定特定的程序被编译的运行时库搜索路径。

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

5 Dynamically Loaded (DL) Libraries

使用动态加载库:

#include <stdlib.h>

#include <stdio.h>

#include <dlfcn.h>

int main(int argc, char **argv) {

void *handle;

double (*cosine)(double);

char *error;

handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);

if (!handle) {

fputs (dlerror(), stderr);

exit(1);

}

cosine = dlsym(handle, "cos");

if ((error = dlerror()) != NULL)  {

fputs(error, stderr);

exit(1);

}

printf ("%f\n", (*cosine)(2.0));

dlclose(handle);

}

编译命令为:

gcc -o foo foo.c -ldl

6 参考

http://tldp.org/HOWTO/Program-Library-HOWTO/

浅析C/C++ library的更多相关文章

  1. 从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler

    熟悉WebForm开发的朋友一定都知道,Page类必须实现一个接口,就是IHttpHandler.HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...

  2. MS SQL统计信息浅析下篇

       MS SQL统计信息浅析上篇对SQL SERVER 数据库统计信息做了一个整体的介绍,随着我对数据库统计信息的不断认识.理解,于是有了MS SQL统计信息浅析下篇. 下面是我对SQL Serve ...

  3. 浅析py-faster-rcnn中不同版本caffe的安装及其对应不同版本cudnn的解决方案

    浅析py-faster-rcnn中不同版本caffe的安装及其对应不同版本cudnn的解决方案 本文是截止目前为止最强攻略,按照本文方法基本可以无压力应对caffe和Ross B. Girshick的 ...

  4. Android Dagger依赖注入框架浅析

    今天接触了Dagger这套android的依赖注入框架(DI框架).感觉跟Spring 的IOC差点儿相同吧.这个框架它的优点是它没有採用反射技术(Spring是用反射的),而是用预编译技术.因为基于 ...

  5. C# 程序性能提升篇-1、装箱和拆箱,枚举的ToString浅析

    前景提要: 编写程序时,也许你不经意间,就不知不觉的使程序代码,发生了装箱和拆箱,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环.网络程序(不断请求处理的)等这些时候,减少装箱和拆 ...

  6. IOCP 浅析

    http://www.ibm.com/developerworks/cn/java/j-lo-iocp/ https://msdn.microsoft.com/en-us/library/window ...

  7. A transition animation compatible Library.

    Android5.0之后为我们提供了许多炫酷的界面过渡效果,其中共享元素过渡也是很有亮点的一个效果,但这个效果只能在Android5.0之后使用,那今天我们就来将共享元素过渡效果兼容到Android4 ...

  8. C# 程序性能提升篇-2、类型(字段类型、class和struct)的错误定义所影响性能浅析

    前景提要: 编写程序时,也许你不经意间,就不知不觉的定义了错误的类型,从而发生了额外的性能消耗,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环.网络程序(不断请求处理的)等这些时候 ...

  9. Reactive Extensions(Rx)并发浅析

    Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...

随机推荐

  1. QT 按钮(4种样式)

    // 1.正常  btnNormal_ = new QPushButton("Normal Button", this);  // 2.可停驻  btnCheck_ = new Q ...

  2. online training

    https://www.skillfeed.com/browse http://teamtreehouse.com/features http://www.pluralsight.com/ https ...

  3. heap size eclipse 堆内存

    可以根据eclipse 或 myeclipse heapstats 使用情况调整堆内存大小,heap size 设置,-vmargs-Xms256-Xmx1024 ,其中Xms表示初始值,Xmx表示最 ...

  4. Notes of the scrum meeting(12.8)

    meeting time:18:00~18:30p.m.,December 8th,2013 meeting place:20号公寓前 attendees: 顾育豪                   ...

  5. 前端之JavaScript第三天学习(7)-JavaScript-数据类型

    字符串.数字.布尔.数组.对象.Null.Undefined JavaScript 拥有动态类型 JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: 实例 var x      ...

  6. 《我是IT一只小小鸟》读后感

    <我是IT一只小小鸟>读后感 首先,非常感谢我的老师给我推荐了这么一本书,虽然刚开始因为这门课学分太低,所以我对老师布置了字数这么多的作业存在有很大的不满,但在看了这本书后我的不满立马得到 ...

  7. 【python】文件的输入和输出

    1.os模块 2.os.path 模块 3.实例 1. os模块 对文件系统的访问大多通过python的os模块实现,其中os 模块负责大部分的文件系统操作,包括删除/重命名文件,遍历目录树,管理文件 ...

  8. 【BZOJ】【3238】【AHOI2013】diff(差异)

    题目链接:www.lydsy.com/JudgeOnline/problem.php?id=3238 后缀数组 这题题面给的暗示性就很强啊……一看就是要用后缀xx一家的算法,由于本蒻只会后缀数组所以就 ...

  9. jquery cdn加速点

    新浪jquery cdn加速点: <script src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.js">< ...

  10. 关于High-Resolution Timer(了解)

    如果一个系统包含高精度性能计数器(HRPC,high-resolution performance counter)则此系统提供高精度定时器.你可以使用API函数QueryPerformanceFre ...