深入探究Linux共享库实现的奥秘 (linux 共享库实现)

Linux操作系统是开源的,其特点之一就是支持共享库的方式实现程序的动态链接。共享库的实现在Linux操作系统中十分重要,它极大地促进了程序的开发、编译和部署。本文将,从共享库的定义、原理、优缺点和应用等方面展开探究。

一、共享库的定义和原理

共享库是指一类可以被多个程序共享使用的代码库,可以被程序动态链接调用。在Linux系统中,共享库通常使用文件名以“.so”结尾的文件。共享库的实现可以有效解决传统的静态链接库方式存在的问题,即节省内存空间,并且可以方便地升级和维护。

共享库实现的原理是将需要共享的代码打包成动态链接库文件,并加载到内存中,程序在运行时可以通过动态链接库调用需要的函数。这种方式可以使得多个程序共用同一个库,避免了重复代码和浪费内存的问题。

二、共享库的优缺点

与静态链接库相比,共享库具有以下优点:

1. 节省内存空间:多个程序可以共用同一个库,避免了重复代码和浪费内存的问题。

2. 程序升级方便:共享库的实现可以方便对库进行升级和维护,而不像静态链接库需要重新编译整个程序。

3. 加快编译速度:编译时只需生成一个共享库文件,而不是多个静态链接库文件,加快了编译速度。

但共享库也存在以下缺点:

1.性能问题:由于动态链接的原因,共享库的性能一般不如静态链接库。

2.兼容问题:由于动态链接的文件版本问题,共享库在不同版本的Linux操作系统中可能存在兼容性问题。

三、共享库的应用

共享库广泛应用于Linux系统下的软件开发和部署,包括:

1.开发工具:如GCC等开发工具本身就是使用共享库的方式实现进而降低不必要的代码冗余。

2.运行库:像C运行库、C++运行库等各种运行库都是使用共享库的方式实现。

3.图形界面库:像GTK、QT等图形界面库都是使用共享库的方式实现。

4.网络库:像OpenSSL、libcurl等网络库也都是使用共享库的方式实现。

共享库是Linux系统中十分重要的实现方式,它的应用广泛,明显提高了程序的开发效率和部署效率。以上我们从共享库的定义、原理、优缺点和应用等方面展开了深入探究Linux共享库的实现奥秘。

相关问题拓展阅读:

linux 用g++编译c++代码的问题

1,注释掉 12行的CLOCKS_PER_SEC

2,你在open之察宽樱前,单独创建一个string对象,把文件巧巧名保存好;

string fullname = “/home/wangwenyu/c13.03/more” + filename + “.in” ;

然后再去调用败丛 fout.open

*

运行 gcc/egcs

*

gcc/egcs 的主要选项

*

gdb

*

gdb 的常用命令

*

gdb 使用范例

*

其他程序/库工具 (ar, objdump, nm, size, strings, strip, …)

* 创建和使用静态库

* 创建和使用共享库

* 使用高级共享库特性

1.7.1 运行 gcc/egcs

Linux 中最重要的软件开发工具是 GCC。GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 Object C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++ 源程序。

#DEMO#: hello.c

如果你有两个或少数几个 C 源文件,也可以方便地利用 GCC 编译、连接并生成可执行文件。例如,假设拦陆烂你有两个源文件 main.c 和 factorial.c 两个源文件,现在要编译生成一个计算阶乘的程序。

清单 factorial.c

#include

#include

int factorial (int n)

{

if (n

#include

int factorial (int n);

int main (int argc, char **argv)

{

int n;

if (argc

void main (void)

{

cout

#include

static char buff ;

static char* string;

int main ()

{

printf (“Please input a string: “);

gets (string);

printf (“\nYour string is: %s\n”, string);

}

上面这个程序非常简单,其目的是接受用户的输入,然后将用户的输入打印出来。该程序使用了

一个未经过初始化的字符串地址 string,因此,编译并运行之后,将出现 Segment Fault 错误:

$ gcc -o test -g test.c

$ ./test

Please input a string: asfd

Segmentation fault (core dumped)

为了查找该程序中出现的问题,我们利用 gdb,并按如下的步骤进行:

1.运行 gdb bugging 命令,装入 bugging 可执行文件;

2.执行装入的 bugging 命令;

3.使用 where 命令查看程序出错的地方;

4.利用 list 命令查看调用 gets 函数附近的代码;

5.唯一能够导致 gets 函数出错的因素就是变量 string。用 print 命令查看 string 的值;

6.在 gdb 中,我们可以直接修改变量的值,只要将 string 取一个合法的指针值就可以了,为

此,我们在第 11 行处设置断点;

7.程序重新运行到第 11 行处停止,这时,我们可以用 set variable 命令修改 string 的取值;

8.然后继续运行,将看到正确的程序运行结果。

#DEMO#

1.7.6 其他程序/库工具

strip:

nm:

size:

string:

1.7.7 创建和使用静态库

创建一个静态库是相当简单的。通常使用 ar 程序把一些目标文件(.o)组合在一起,成为一个单独的库,然后运行 ranlib,以给库加入一些索引信息。

1.7.8 创建和使用共享库

特殊的编译和连接选项

-D_REENTRANT使得预处理器符号 _REENTRANT 被定义,这个符号激活一些宏特性。

-fPIC 选项产生位置独立的代码。由于库是在运行的时候被调入,因此这个

选项是必需的,因为在编译的时候,装入内存的地址还不知道。如果

不使用这个选项,库文件可能不会正确运行。

-shared选项告诉编译器产生共享库代码。

-Wl,-sonameWl 告诉编译器将后面的参数传递到连接器。而 -soname 指定了

共享库的 soname。

# 可以把库文件拷贝到 /etc/ld.so.conf 中列举出的任何目录中,并以

root 身份运行 ldconfig;或者

# 运行 export LD_LIBRARY_PATH=’pwd’,它把当前路径加到库搜索路径中去。

1.7.9 使用高级共享库特性

1. ldd 工具

ldd 用来显示执行文件需要哪些共享库, 共享库装载管理器在哪里找到了需要的共享库.

2. soname

共享库的一个非常重要的,也是非常难的概念是 soname——简写共享目标名(short for shared object name)。这是一个为共享库(.so)文件而内嵌在控制数据中的名字。如前面提到的,每一个程序都有一个需要使用的库的清单。这个清单的内容是一系列库的 soname,如同 ldd 显示的那样,共享库装载器必须找到这个清单。

soname 的关键功能是它提供了兼容性的标准。当要升级系统中的一个库时,并且新库的 soname 和老的库的 soname 一样,用旧库连接生成的程序,使用新的库依然能正常运行。这个特性使得在 Linux 下,升级使用共享库的程序和定位错误变得十分容易。

在 Linux 中,应用程序通过使用 soname,来指定所希望库的版本。库作者也可以通过保留或者改变 soname 来声明,哪些版本是相互兼容的,这使得程序员摆脱了共享库版本冲突问题的困扰。

查看/usr/local/lib 目录,分析 MiniGUI 的共享库文件之间的关系

3. 共享库装载器

当程序被调用的时候,Linux 共享库装载器(也被称为动态连接器)也自动被调用。它的作用是保证程序所需要的所有适当版本的库都被调入内存。共享库装载器名字是 ld.so 或者是 ld-linux.so,这取决于 Linux libc 的版本,它必须使用一点外部交互,才能完成自己的工作。然而它接受在环境变量和配置文件中的配置信息。

文件 /etc/ld.so.conf 定义了标准系统库的路径。共享库装载器把它作为搜索路径。为了改变这个设置,必须以 root 身份运行 ldconfig 工具。这将更新 /etc/ls.so.cache 文件,这个文件其实是装载器内部使用的文件之一。

可以使用许多环境变量控制共享库装载器的操作(表1-4+)。

表 1-4+ 共享库装载器环境变量

变量含义

LD_AOUT_LIBRARY_PATH除了不使用 a.out 二进制格式外,与 LD_LIBRARY_PATH 相同。

LD_AOUT_PRELOAD除了不使用 a.out 二进制格式外,与 LD_PRELOAD 相同。

LD_KEEPDIR 只适用于 a.out 库;忽略由它们指定的目录。

LD_LIBRARY_PATH将其他目录加入库搜索路径。它的内容应该是由冒号

分隔的目录列表,与可执行文件的 PATH 变量具有相同的格式。

如果调用设置用户 ID 或者进程 ID 的程序,该变量被忽略。

LD_NOWARN 只适用于 a.out 库;当改变版本号是,发出警告信息。

LD_PRELOAD 首先装入用户定义的库,使得它们有机会覆盖或者重新定义标准库。

使用空格分开多个入口。对于设置用户 ID 或者进程 ID 的程序,

只有被标记过的库才被首先装入。在 /etc/ld.so.perload 中指定

了全局版本号,该文件不遵守这个限制。

4. 使用 dlopen

另外一个强大的库函数是 dlopen()。该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。比如 Apache Web 服务器利用这个函数在运行过程中加载模块,这为它提供了额外的能力。一个配置文件控制了加载模块的过程。这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了。

可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。它需要两个参数:一个文件名和一个标志。文件名可以是我们学习过的库中的 soname。标志指明是否立刻计算库的依赖性。如果设置为 RTLD_NOW 的话,则立刻计算;如果设置的是 RTLD_LAZY,则在需要的时候才计算。另外,可以指定 RTLD_GLOBAL,它使得那些在以后才加载的库可以获得其中的符号。

linux的shell编程与用gcc实现c编程有什么不同?有什么优点?

shell编程属于脚本编程,脚本文件就是指令的,GCC是GNU编译系统驱动程序。

Linux中的库分两种:静态库和共享库。静态库以.a结尾,也叫归档文件(archive),类似于windows中的.lib文件,他的缺点是同时运行的多个程序使用同个函数库函数时,内存中会有多个该函数及该程序文件的副本,浪费了内存。共享库以.so结尾乎罩,类似于windows中的.Dll文件。

shell是对linux内核岁逗闹的一种封装,提供了一些函数的接口,shell程序设计就是利用这些函数接口进行编程。

完全是两个方向的应用。总的来说,不具备可比性。但实际要看应用环境。相对来说,shell 的程序还是以简单的功能为主。大型的应用程序还是 C 语言指轮更合适。

linux 共享库实现的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux 共享库实现,深入探究Linux共享库实现的奥秘,linux 用g++编译c++代码的问题,linux的shell编程与用gcc实现c编程有什么不同?有什么优点?的信息别忘了在本站进行查找喔。


数据运维技术 » 深入探究Linux共享库实现的奥秘 (linux 共享库实现)