你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

讨论linux下的库

[复制链接]
gaosmile 发布时间:2020-11-20 20:02
[导读]本文仅讨论linux下的库。1 j  W1 S9 ~0 I# Y+ b. z1 r

; c; k3 W) M& @* Z  r. M! Y

: L$ j7 }" j7 W: b/ q  Y  g- t
" q$ g4 e% j7 Z( ]: I, l1 z
7 G+ _: ~6 @; ^6 \, G

一口君中学阶段最喜欢的一首歌。

窦仙才华横溢、潇洒不羁、与世无争,酷的外焦里嫩!

让我们随着窦仙高昂的声音来学习什么是(酷)库吧!% N0 V9 v  L* o! Z

一、什么是库?

在windows平台和linux平台下都大量存在着库。一般是软件作者为了发布方便、替换方便或二次开发目的,而发布的一组可以单独与应用程序进行compile time或runtime链接的二进制可重定位目标码文件。

本质上来说库是一种可执行代码的二进制形式,这个文件可以在编译时由编译器直接链接到可执行程序中,也可以在运行时由操作系统的runtime enviroment根据需要动态加载到内存中。

一组库,就形成了一个发布包,当然,具体发布多少个库,完全由库提供商自己决定。

由于windows和linux的本质不同,因此二者库的二进制是不兼容的。

现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。

共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

本文仅讨论linux下的库。

二、库的分类

库有两种:静态库和共享库(动态库)。

win32平台下,静态库通常后缀为.lib,动态库为.dll]int add(int x,int y)
3 J2 N+ j3 p1 t{
% [5 O) h5 V) C1 g     return x+y;: r8 z# V# _1 g/ h1 x. @
}
4 p  l- Q; }. n7 iint sub(int x,int y)
) ]2 J7 J" i$ y: x! i9 o3 @# Z9 u{
( ]( b5 E9 ?& G: M3 p8 K     return x-y;
2 m* Y" E- \' \* c4 ~3 Z, Z* l}
- s7 L& y1 V# J& A% c$ b9 V- X

add.h

<span]<span]gcc -c add.c
4 J7 m7 t  B! V& E" m# t
  • 使用 ar 命令生成静态库libadd.a% E  R8 W; K9 u- x& H
ar]#include 8 T' c; P" U" U7 h* Y0 u  u' M% g
#include "add.h") x. T% K. l% J+ c5 c- W6 e
void main()
3 E+ x8 E$ [* Y, ]1 ]{8 a# J3 g2 Y  N4 L5 N9 \- O
    printf("add(5,4) is %d\n",add(5,4));
. A4 b* H8 P( c    printf("sub(5,4) is %d\n",sub(5,4));+ `0 r5 T3 ~- ^; o8 }. i
}) ~6 ~$ q, }# Z0 X' P$ N  U

静态库的文件可以放在任意的位置,编译时只需要找到该库文件即可。

gcc]gcc -c -I /home/xxxx/include test.c //假设test.c要使用对应的静态库7 `2 S7 h" o; V. J
gcc -o test -L /home/xxxxx/lib test.o libadd.a# T, C4 t9 ]' [( r- H) l& R/ j

或者

gcc]gcc -fPIC -o libadd.o -c add.c9 [. U; X; T+ U4 g/ s0 u; f( F
gcc -shared -o libadd.so libadd.o$ F1 P% g/ s$ p! O$ I9 i5 R. S

也可以直接使用一条命令

gcc]sudo cp libadd.so /lib
% q* e( }& ]5 P% R1 u+ I2 L
  • 使用动态库+ i" y- A  t# |* }! |0 H; t8 I
<span]<span]gcc static -o run  -ladd# P# f$ l; \( o6 p

注意观察编译时动态库的名字与库文件对应关系

libadd.so<--------->-ladd
% _2 ~/ V% }" E0 B8 ^* x. O
[p=26,]libadd.so<--------->-ladd
# J; |$ K5 t8 @2 j* B
[p=26,]
void * dlopen(const char *filename, int flag);
- [7 T# p8 l9 w7 I( F- { 参数1 a  h% [7 Y. B1 M& x7 O& Z

/ y" K7 a$ [% m) n5 Q0 C8 Dfilename8 D: y( ?) ^/ |$ L  n/ e8 T
如果文件名filename是以“/”开头,也就是使用绝对路径,那么dlopne就直接使用它,而不去查找某些环境变量或者系统设置的函数库所在的目录了。否则dlopen()就会按照下面的次序查找函数库文件:1 k( ~2 e8 T$ U' A1 h/ V1 a# p
1. 环境变量LD_LIBRARY指明的路径。
! G9 |) w, W/ K. |2. /etc/ld.so.cache中的函数库列表。
6 @% B1 S+ P+ Y7 z& U: Y3. /lib目录,然后/usr/lib。) z/ C8 n$ X' k5 |" E6 @

) f$ o" N9 o# b0 e- V$ m一些很老的a.out的loader则是采用相反的次序,也就是先查 /usr/lib,然后是/lib。7 s( f8 l: }  o2 s/ q( w% V
, d" P4 |! ]: q3 ?0 i8 O# w/ h
flag
# `4 x. H) P9 R1 n) S的值必须是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolve undefined symbols as code from the dynamic library is executed,而RTLD_NOW的含义是resolve all undefined symbols before dlopen() returns and fail if this cannot be done'。
  F1 n' F$ ]3 @返回值
2 S1 x7 r/ w" t. c. Vdlopen()函数的返回值是一个句柄,然后后面的函数就通过使用这个句柄来做进一步的操作。如果打开失败dlopen()就返回一个NULL。如果一个函数库被多次打开,它会返回同样的句柄。 / j7 h1 ^/ c9 ~* X
( z8 I% S" c: @7 ^6 h' }

如果有好几个函数库,它们之间有一些依赖关系的话,例如X依赖Y,那么你就要先加载那些被依赖的函数。例如先加载Y,然后加载X。

dlerror()

通过调用dlerror()函数,我们可以获得最后一次调用dlopen(),dlsym(),或者dlclose()的错误信息。

dlsym()

如果你加载了一个DL函数库而不去使用当然是不可能的了,使用一个DL函数库的最主要的一个函数就是dlsym(),这个函数在一个已经打开的函数库里面查找给定的符号。这个函数如下定义:

]参数
0 L' X. D  O7 U. m6 ^# whandle) X* T* S. `& z  M& Z
就是由dlopen打开后返回的句柄,& \- ]# G5 k) n6 H. J+ T1 f  B
symbol
3 L7 V' C1 f9 o  z+ A) ~8 }是一个以NIL结尾的字符串。7 C2 ?" i' s+ ]4 V9 {$ w/ B
功能:. M# _9 K9 [& ]
如果dlsym()函数没有找到需要查找的symbol,则返回NULL。如果你知道某个symbol的值不可能是NULL或者0,那么就很好,你就可以根据这个返回结果判断查找的symbol是否存在了;不过,如果某个symbol的值就是NULL,那么这个判断就有问题了。标准的判断方法是先调用dlerror(),清除以前可能存在的错误,然后调用dlsym()来访问一个symbol,然后再调用dlerror()来判断是否出现了错误。
1 d! ~1 Y6 @- j( C8 R

dlclose()

dlopen()函数的反过程就是dlclose()函数,dlclose()函数用力关闭一个DL函数库。Dl函数库维持一个资源利用的计数器,当调用dlclose的时候,就把这个计数器的计数减一,如果计数器为0,则真正的释放掉。真正释放的时候,如果函数库里面有_fini()这个函数,则自动调用_fini()这个函数,做一些必要的处理。Dlclose()返回0表示成功,其他非0值表示错误。

举例

<span]<span] vi /etc/profile0 F( a5 n. `& ?) G. z

在文件里末尾加上对应的环境变量信息。

动态库环境变量设置:

<span]<span]source /etc/profile* i1 _& E2 p! i/ L3 F' D2 |, @0 _
3./etc/ld.so.conf

编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

vim]/usr/local/lib/
2 K3 U4 m# c0 f. w0 p

运行ldconfig,该命令会重建/etc/ld.so.cache文件

七、常见库的移植1.jpeg库,用于jpeg图像处理

下载地址:

http://www.ijg.org/files/

解压

tar]./configure --host=arm-linux-gnueabihf --prefix=$PWD/temp_install0 M+ V9 ~1 N$ G" j

编译,   安装

] mkdir -p /home/peng/jpeg-6b/temp_install/include
4 A1 A8 @/ `$ E9 _+ B! ~4 F mkdir -p /home/peng/jpeg-6b/temp_install/lib
8 {; ?) b% A* L mkdir -p /home/peng/jpeg-6b/temp_install/man/man1  

; j) X: C& {' X- t
: X6 _. r1 |( N6 Y& v4 l0 H8 I
  X) Z% g8 l, h0 R

6 G1 H+ Z- V7 l; |) n
赞 收藏 评论0 发布时间:2020-11-20 20:02

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版