来自 服务器&运维 2020-02-15 17:52 的文章
当前位置: 澳门威尼斯人平台 > 服务器&运维 > 正文

Linux静态库和动态库

几这段时间大家根本来讲说Linux系统下基于动态库(.so卡塔尔(قطر‎和静态(.a卡塔尔国的顺序那贰个猫腻。在这里前边,大家供给了然一下源代码到可执路程序之间到底发生了怎么样神奇而卓越的作业。

 

本文同步发布于作者的私家网址:Linux静态库和动态库

在Linux操作系统中,广泛选取ELF格式作为可执路程序或许程序生成进程中的中间格式。ELF(Executable and Linking Format,可执行连接格式)是UNIX系统实验室(USL)作为应用程序二进制接口(Application BinaryInterface,ABI)而开拓和公布的。工具接口规范委员会(TIS)接收了正在发展中的ELF规范作为职业在33个人英特尔体系上不一样操作系统之间可移植的二进制文件格式。本文不对ELF文件格式及其构成做太多解释,以防冲淡本文的宗旨,我们假使通晓那样个概念就能够。以往再安详严整Linux中的ELF格式。源代码到可执路程序的更动时要求经历如下图所示的经过:

生机勃勃、静态库的成立和接纳:


图片 1

1、生成静态库 :库名 libmylib.a

Linux静态库和动态库

在windows平台和linux平台下都大量存在着库。本质上来讲库是生机勃勃种可履行的二进制代码(但无法独立试行State of Qatar,能够被操作系统载入内部存款和储蓄器实施。

Linux下的库有两种:静态库和动态库(分享库)。

正文将介绍Linux下静态库和动态库的定义以致相应的创办与使用办法,作品内容为私有学习笔记,招待指正。

  • 编写翻译是指把用高等语言编写的程序转变来相应微机的汇编语言程序的进程。从本质上讲,编写翻译是一个文件转变的经过。对嵌入式系统来说,平时要把用C语言编写的程序调换来Computer的汇编代码。编写翻译进程富含了C语言的语法拆解解析和汇编码的变动七个步骤。编写翻译日常是各样文件举行的,对于每叁个C语言编写的文本,恐怕还索要开展预管理。
  • 汇编是从汇编语言程序生成指标体系的二进制代码(机器代码)的历程。机器代码的变动和计算机有精心的联系。相对于编写翻译进程的语法解析,汇编的进度相对轻易。那是因为对此意气风发款特定的微管理机,其汇编语言和二进制的机器代码是逐豆蔻梢头对应的。汇编过程的输入是汇编代码,那么些汇编代码只怕源于编写翻译进度的出口,也足以是直接用汇编语言书写的顺序。
  • 三回九转是指将汇编生成的多段机器代码组合成一个可执路程序。通常的话,通过编写翻译和汇编进程,每种源文件将生成二个目标文件。连接器的作用就是将那个目的文件组合起来,组合的进度包蕴了代码段、数据段等部分的联结,以至足够相应的文件头。

ar rcs libmylib.a mylib.o

1 对比

类型 特点
静态库 在编译时被链接到程序中,作为可执行程序的一部分。在程序运行时不再依赖静态库,占用内存大
动态库 在可执行程序运行时载入内存。动态库已经在内存中不需要再次载入

GCC是Linux下第豆蔻梢头的次第生成工具,它除了编写翻译器、汇编器、连接器外,还包含一些支持理工科程师具。在上边包车型大巴剖判进度中笔者会教我们那一个工具的骨干选用方式,Linux的强有力之处在于,对于不太懂的指令或函数,有一个很有力的“男子”时刻stand by your side,有哪些不会的就去命令行终端输入:man [一声令下名或函数名],然后阿拉神灯就能够显灵了。

2、将静态库copy到 /usr/lib/ 或/lib/ 目录下

2 静态库

对此最终编译出来的可施行程序,当我们实行它的时候,操作系统又是哪些反馈的吧?大家先从微观上来个完全把握,如图2所示:

cp libmylib.a /usr/lib/

2.1 概念

静态库指将全部有关的靶子文件打包成为叁个单独的文书,即静态库文件

静态库以.a终极,链接器会将顺序中利用到的函数的代码从库文件中拷贝到程序中。

是因为种种使用静态库的应用程序都供给拷贝全体函数的代码,所以静态链接的文本会比较

在Unix系统中,静态库以一种名称叫存档(archive)的独特文件格式寄放在磁盘中。

存档文件是风流罗曼蒂克组连接起来的可重定位目的文件的集聚,有二个头顶用来说述种种成员目的文件的大大小小和任务。

图片 2

3、静态库的选拔

2.2 静态库的创始和行使

用作UNIX操作系统的后生可畏种,Linux的操作系统提供了生龙活虎多级的接口,那几个接口被叫作系统调用(System Call)。在UNIX的见地中,系统调用“提供的是体制,并不是战略“。C语言的库函数通过调用系统调用来兑现,库函数对上层提供了C语言库文件的接口。在利用程序层,通过调用C语言库函数和种类调用来落时间效益果与利益。常常的话,应用程序相当多使用C语言库函数完成其效劳,很少使用系统调用。

比方测验文件为test.c

2.2.1 情况希图

开创根文件夹staticDemo:

[root@VM_120_243_centos ~]# mkdir staticDemo

成立子文件夹include,用于贮存全数头文件:

[root@VM_120_243_centos ~]# cd staticDemo/
[root@VM_120_243_centos staticDemo]# mkdir include

进入include文件夹,编写myLib.h文件,申明printInfo()函数:

[root@VM_120_243_centos staticDemo]# cd include/
[root@VM_120_243_centos include]# vim myLib.h
[root@VM_120_243_centos include]# cat myLib.h 
void printInfo();

进去上层目录,成立lib文件夹,用于寄放全部库文件,再当中编写print.c文件,使用了myLib.h中的printInfo()函数:

[root@VM_120_243_centos include]# cd ..
[root@VM_120_243_centos staticDemo]# mkdir lib
[root@VM_120_243_centos staticDemo]# cd lib/
[root@VM_120_243_centos lib]# vim print.c
[root@VM_120_243_centos lib]# cat print.c 
#include <stdio.h>
#include "myLib.h"

void printInfo()
{
    printf("print from print.c file...n");
}

进去上层目录,编写main.c文本,用于测量试验:

[root@VM_120_243_centos lib]# cd ..
[root@VM_120_243_centos staticDemo]# vim main.c
[root@VM_120_243_centos staticDemo]# cat main.c 
#include <stdio.h>
#include "myLib.h"

int main(void)
{
    printf("print from main.c file...n");
    printInfo();
    return 0;
}

筹划事业到此形成,整个目录构造如下:

[root@VM_120_243_centos staticDemo]# tree
.
├── include
│   └── myLib.h
├── lib
│   └── print.c
└── main.c

2 directories, 3 files

那么最后的可实践文件到底是怎么样体统吗?前面已经说过,这里我们不拆解深入分析ELF文件的格式,只是给出它的叁个构造图和一些简便的辨证,以方便大家精晓。

gcc -0 test test.c -lmylib

2.2.2 生成静态库

第意气风发进入lib文件夹,生成print.o文件:

[root@VM_120_243_centos staticDemo]# cd lib/
[root@VM_120_243_centos lib]# gcc -c print.c -I../include/ -o print.o
[root@VM_120_243_centos lib]# ls
print.c  print.o

使用ar命令归档目的文件,获得静态库:

[root@VM_120_243_centos lib]# ar -crv libprint.a print.o
a - print.o
[root@VM_120_243_centos lib]# ls
libprint.a  print.c  print.o

上述命令中crvar的指令选项:

  • c 如若供给生成新的库文件,不要警示

  • r 取代库中现成的公文也许插入新的文件

  • v 输出详细音信

使用-t参数可以查阅静态库中隐含的文书:

[root@VM_120_243_centos lib]# ar -t libprint.a 
print.o

注意:咱俩要调换的库的文件名必需形如libxxx.a,那样我们在链接这一个库时,就足以用-lxxx

反过来说,当大家告知编写翻译器-lxxx时,编写翻译器就能够在钦命的目录中寻觅libxxx.a或是libxxx.so

ELF文件格式包涵二种关键的档期的顺序:可施行文件、可重定向文件、分享库。

-l为筛选, mylib为库名。mylib为libmylib的中游有个别,Linux下约定全体库都是前缀lib开头

2.2.3 生成可实践文件

步向上层目录,链接库并转移可试行文件:

[root@VM_120_243_centos staticDemo]# gcc main.c -I./include/ -L./lib/ -lprint -o main

施行可实践文件:

[root@VM_120_243_centos staticDemo]# ./main 
print from main.c file...
print from print.c file...

1.可施行文件(应用程序)

静态库以.a结尾,动态库以.so结尾。再编写翻译程式时,无需带上前缀和后缀。

3 动态库

可试行文件包蕴了代码和数码,是足以直接运维的前后相继。

只顾:静态库的命名须求以"lib"最早,否者连接是编写翻译器不可能找到库

3.1 概念

动态库是一个目标模块,Linux系统以.so后缀表示,Windows以.dll后缀表示,使用动态库能够减小应用程序占用的上空和加载时间。

在运作时,可以加载到自由的存款和储蓄器地址,并和三个再存储器中的程序链接起来,那一个进程称为动态链接,是由三个名称叫动态链接器的主次来实施的。

动态库是Linux系统最广泛的生机勃勃种程序行使办法,工作原理是均等效果的代码能够被四个程序生龙活虎道接纳

在前后相继加载的时候,内核会检查程序使用到的动态库是不是业已加载到内存:

  • 固然未有被加载到内部存储器,则从系统库路线寻找並且加载到有关的动态库。

  • 譬喻动态库已经被加载到内部存款和储蓄器,程序能够直接行使而没有需求加载。

应用程序在自个儿加载时运维进程中动态链接和加载动态库。

2.可重定向文件(*.o)

二、动态库的创始和应用:

3.2 动态库的创办和平运动用

可重定向文件又称之为目的文件,它含有了代码和数目(那个多少是和其余重向来文件和分享的object文件一同三番五次时选择的)。

1、上面木鸡养到把mylib.c程序创立成了八个动态库

3.2.1 境遇盘算

开创根文件夹dynamicDemo:

[root@VM_120_243_centos ~]# mkdir dynamicDemo

创造子文件夹include,用于存放全数头文件:

[root@VM_120_243_centos ~]# cd dynamicDemo/
[root@VM_120_243_centos dynamicDemo]# mkdir include

进入include文件夹,编写myLib.h文件,申明printInfo()函数:

[root@VM_120_243_centos dynamicDemo]# cd include/
[root@VM_120_243_centos include]# vim myLib.h
[root@VM_120_243_centos include]# cat myLib.h 
void printInfo();

进去上层目录,创制lib文件夹,用于寄放全部库文件,再在那之中编写print.c文件,使用了myLib.h中的printInfo()函数:

[root@VM_120_243_centos include]# cd ..
[root@VM_120_243_centos dynamicDemo]# mkdir lib
[root@VM_120_243_centos dynamicDemo]# cd lib/
[root@VM_120_243_centos lib]# vim print.c
[root@VM_120_243_centos lib]# cat print.c 
#include <stdio.h>
#include "myLib.h"

void printInfo()
{
    printf("print from print.c file...n");
}

进去上层目录,编写main.c文本,用于测量试验:

[root@VM_120_243_centos lib]# cd ..
[root@VM_120_243_centos dynamicDemo]# vim main.c
[root@VM_120_243_centos dynamicDemo]# cat main.c 
#include <stdio.h>
#include "myLib.h"

int main(void)
{
    printf("print from main.c file...n");
    printInfo();
    return 0;
}

盘算专门的工作到此造成,整个目录构造如下:

[root@VM_120_243_centos dynamicDemo]# tree
.
├── include
│   └── myLib.h
├── lib
│   └── print.c
└── main.c

2 directories, 3 files

*.o文件参预程序的连天(创设三个程序)和次序的实施(运营二个顺序),它提供了二个有助于实用的法门来用并行的理念看待文件的剧情,这一个*.o文件的移位得以反映出分化的内需。

(1)、gcc -fPIC -o mylib.o -c mylib.c

3.2.2 生成动态库

进入lib文件夹,给gcc加入-fPIC参数,生成print.o文件:

[root@VM_120_243_centos dynamicDemo]# cd lib/
[root@VM_120_243_centos lib]# gcc -c print.c -fPIC -I../include/ -o print.o
[root@VM_120_243_centos lib]# ls
print.c  print.o

使用gcc的-shared参数变化动态库libprint.so:

[root@VM_120_243_centos lib]# gcc -shared print.o -o libprint.so
[root@VM_120_243_centos lib]# ls
libprint.so  print.c  print.o

Linux下,大家得以用gcc -c编写翻译源文件时可将其编写翻译成*.o格式。

(2)、gcc -shared -o libttt.so mylib.o

3.2.3 生成可试行文件

进入dynamicDemo目录,链接库并生成可实施文件:

[root@VM_120_243_centos dynamicDemo]# gcc main.c -I./include/ -L./lib/ -lprint -o main

注意:假定生机勃勃致目录下同时设有同名的动态库和静态库,比如libprint.solibprint.a都在现阶段路径下,则gcc会开始时期链接动态库

实施可实践文件:

[root@VM_120_243_centos dynamicDemo]# ./main 
./main: error while loading shared libraries: libprint.so: cannot open shared object file: No such file or directory

系统报错找不到libprint.so,原来Linux是通过/etc/ld.so.cache文本搜寻要链接的动态库的。而/etc/ld.so.cacheldconfig程序读取/etc/ld.so.conf文本生成的。(注意,/etc/ld.so.conf中并不必包含/lib/usr/libldconfig前后相继会自行检索那八个目录)

此处大家内定意况变量来找到动态库路线,在下风度翩翩节中会有详尽介绍:

[root@VM_120_243_centos dynamicDemo]# LD_LIBRARY_PATH=./lib/ ./main
print from main.c file...
print from print.c file...

3.分享文件(*.so)

也能够直接使用一条命令

3.3 设置动态库的搜寻路线

也称为动态库文件,它蕴涵了代码和数据(这么些数量是在一而再再而三时候被连接器ld和平运动转时动态连接器使用的)。动态连接器或许称为ld.so.1,libc.so.1只怕 ld-linux.so.1。作者的CentOS6.0系统中该文件为:/lib/ld-2.12.so

gcc -fPIC -shared -o libttt.so mylib.c

3.3.1 LD_LIBRARY_PATH

LD_LIBRARY_PATH是Linux情状变量名,该情形变量主要用以在追寻动态库时寻找默许路径之外的其余门路。

万般,Linux寻找动态库的私下认可路线是/lib/usr/libLD_LIBRARY_PATH路径优先级大于系统暗中同意路径。

[root@VM_120_243_centos dynamicDemo]# gcc main.c -I./include/ -L./lib/ -lprint -o main
[root@VM_120_243_centos dynamicDemo]# LD_LIBRARY_PATH=./lib/ ./main
print from main.c file...
print from print.c file...

图片 3

2、Linux有三种方法调用动态库连接中的函数

3.3.2 rpath

gcc的-Wl,-rpath慎选在编写翻译链接时钦赐动态库路线,並且将动态库路线保存到可施行文件中。运维可实行文件时直接到该路径下搜寻动态库,而不依据于于暗中同意路线大概情状变量。

[root@VM_120_243_centos dynamicDemo]# gcc main.c -I./include/ -L./lib/ -lprint -Wl,-rpath=./lib -o main
[root@VM_120_243_centos dynamicDemo]# ./main 
print from main.c file...
print from print.c file...

接受这种措施,每一种程序能够设定独立的动态库地方,而不会像LD_LIBRARY_PATH情形变量那样影响此外程序。

多少个ELF文件从连接器(Linker)的角度看,是部分节的会见;从程序加载器(Loader)的角度看,它是有的段(Segments)的汇集。ELF格式的顺序和分享库具备相仿的布局,只是段的集中和节的集合上稍加差异。

(1)、gcc -o test test.c ./libttt.so

3.3.3 ldconfig

ldconfig是一个动态链接库管理命令。该命令的用项是在暗中认可路线(/lib/usr/lib)以至动态库配置文件/etc/ld.so.conf内所包括的目录下,寻找动态库,然后为动态载入程序(ld.so)创设动态库列表的缓存文件(/etc/ld.so.cache)

那么毕竟如何是库呢?

(2)、cp libttt.so /usr/lib/libttt.so

3.3.3.1 参与正规路线

此地以放入/usr.lib文件夹为例:

[root@VM_120_243_centos dynamicDemo]# cp ./lib/libprint.so /usr/lib/

履新缓存:

[root@VM_120_243_centos dynamicDemo]# ldconfig

翻看动态库:

[root@VM_120_243_centos dynamicDemo]# ldconfig -p | grep libprint.so
    libprint.so (libc6,x86-64) => /lib/libprint.so

编写翻译实行:

[root@VM_120_243_centos dynamicDemo]# gcc main.c -I ./include/ -L ./lib/ -lprint -o main
[root@VM_120_243_centos dynamicDemo]# ./main 
print from main.c file...
print from print.c file...

库从实质上来讲是风流倜傥种可推行代码的二进制格式,可以被载入内部存款和储蓄器中执行。库分静态库和动态库二种。

gcc -o test test.c /usr/lib/libttt.so

3.3.3.2 参预配置文件

首先查看/etc/ld.so.conf文件:

[root@VM_120_243_centos dynamicDemo]# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf

能够见到其富含了ld.so.conf.d目录,因而自定义配置文件libprint.conf加入到/etc/ld.so.conf.d文本夹中,配置文件中饱含该程序的动态库路线:

[root@VM_120_243_centos dynamicDemo]# pwd
/root/dynamicDemo
[root@VM_120_243_centos dynamicDemo]# vim /etc/ld.so.conf.d/libprint.conf
[root@VM_120_243_centos dynamicDemo]# cat /etc/ld.so.conf.d/libprint.conf
/root/dynamicDemo/lib

革新缓存:

[root@VM_120_243_centos dynamicDemo]# ldconfig

查看动态库:

[root@VM_120_243_centos dynamicDemo]# ldconfig -p | grep libprint.so
    libprint.so (libc6,x86-64) => /root/dynamicDemo/lib/libprint.so

编写翻译推行:

[root@VM_120_243_centos dynamicDemo]# gcc main.c -I ./include/ -L ./lib/ -lprint -o main
[root@VM_120_243_centos dynamicDemo]# ./main 
print from main.c file...
print from print.c file...

本文由澳门威尼斯人平台发布于服务器&运维,转载请注明出处:Linux静态库和动态库

关键词: