新闻  |   论坛  |   博客  |   在线研讨会
Linux——C库
电子禅石 | 2021-03-15 23:46:11    阅读:1595   发布文章

Linux——C库

1、库的概念
库是一个二进制文件,包含的代码可被程序调用
标准C库、数学库、线程库……
库有源码,可下载后编译;也可以直接安装二进制包
/lib /usr/lib

2、库的知识
库是事先编译好的,可以复用的代码。
在OS上运行的程序基本上都要使用库。使用库可以提高开发效率。
Windows和Linux下库文件的格式不兼容
Linux下包含静态库和共享库

3、静态库特点
编译(链接)时把静态库中相关代码复制到可执行文件中
程序中已包含代码,运行时不再需要静态库
程序运行时无需加载库,运行速度更快
占用更多磁盘和内存空间
静态库升级后,程序需要重新编译链接

4、静态库创建
a、确定库中函数的功能、接口
b、编写库源码hello.c
#include <stdio.h>
void hello(void) {
printf(“hello world\n”);
return;
  }
c、编译生成目标文件
$ gcc -c hello.c –Wall
d、创建静态库 hello
$ ar crs libhello.a hello.o
e、查看库中符号信息
$nm libhello.a
hello.o:
0000000    T hello
                 U puts

5、链接静态库
a、编写应用程序test.c
#include <stdio.h>
void hello(void);
int main() {
hello();
return 0;
}
b、编译test.c 并链接静态库libhello.a
$ gcc -o test test.c -L. -lhello
$ ./test
hello world

6、共享库特点
编译(链接)时仅记录用到哪个共享库中的哪个符号,不复制共享库中相关代码
程序不包含库中代码,尺寸小
多个程序可共享同一个库
程序运行时需要加载库
库升级方便,无需重新编译程序
使用更加广泛

7、共享库创建
a、确定库中函数的功能、接口
b、编写库源码hello.c bye.c
#include <stdio.h>
void hello(void) {
printf(“hello world\n”);
return;
}
#include <stdio.h>
void bye(void) {
printf(“bye\n”);
return;
  }
c、编译生成目标文件
$ gcc -c -fPIC hello.c bye.c -Wall
d、创建共享库 common
$ gcc -shared -o libcommon.so.1 hello.o bye.o
e、为共享库文件创建链接文件
$ ln -s libcommon.so.1 libcommon.so
f、符号链接文件命名规则
lib<库名>.so

8、链接共享库
a、编写应用程序test.c
#include <stdio.h>
void hello(void);
void bye(void);
int main() {
hello();
bye();
return 0;
}
b、编译test.c 并链接共享库libcommon.so
$ gcc -o test test.c -L. –lcommon
注:-l参数和-L参数
-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。比如我们自已要用到一个第三方提供的库文件libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了。放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概意思是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它放在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest。另外,大部分libxxxx.so只是一个链接,以RH9为例,比如libm.so它链接到/lib/libm.so.x,/lib/libm.so.6又链接到/lib/libm-2.3.2.so,如果没有这样的链接,还是会出错,因为ld只会找libxxxx.so,所以如果你要用到xxxx库,而只有libxxxx.so.x或者libxxxx-x.x.x.so,做一个链接就可以了ln -s libxxxx-x.x.x.so libxxxx.so

9、加载共享库
执行程序
$ ./test
./test: error while loading shared libraries: libcommon.so
cannot open shared object file : No such file or directory
添加共享库的加载路径
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
$ ./test
hello world
bye!

10、如何找到共享库
为了让系统能找到要加载的共享库,有三种方法 :
把库拷贝到/usr/lib和/lib目录下
在LD_LIBRARY_PATH环境变量中添加库所在路径
添加/etc/ld.so.conf.d/*.conf文件,执行ldconfig刷新


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客