当前位置:首页 » 《我的小黑屋》 » 正文

【Linux系统编程】第三十二弹---动态库实战指南:从零构建与高效集成的奥秘

10 人参与  2024年11月02日 12:01  分类 : 《我的小黑屋》  评论

点击全文阅读


✨个人主页: 熬夜学编程的小林

?系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、动态库 

1.1、怎么做动态库

1.2、怎么使用动态库 

2、外部库使用


1、动态库 

1.1、怎么做动态库

方式一

1、将.c文件编译成.o文件

[jkl@host lib]$ gcc -c mystdio.c[jkl@host lib]$ gcc -c mymath.c[jkl@host lib]$ lslibmyc.a  mylib     mymath.h  mystdio.c  mystdio.o main.c    mymath.c  mymath.o  mystdio.h  roommate   

2、将.o文件打包成动态库文件 

[jkl@host lib]$ gcc *.o -o libmyc.so/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':(.text+0x20): undefined reference to `main'collect2: error: ld returned 1 exit status[jkl@host lib]$ gcc -shared *.o -o libmyc.so/usr/bin/ld: mystdio.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC/usr/bin/ld: final link failed: Nonrepresentable section on outputcollect2: error: ld returned 1 exit status
shared: 表示生成共享库格式

上面的方式不能打包成动态库文件,需要在编译成.o文件时加选项

方式二

1、删除前面编译的.o文件

[jkl@host lib]$ rm *.o[jkl@host lib]$ lslibmyc.a  main.c  mylib  mymath.c  mymath.h  mystdio.c  mystdio.h  roommate  

 2、将.c文件编译成.o文件(加选项)

[jkl@host lib]$ gcc -fPIC -c mymath.c[jkl@host lib]$ gcc -fPIC -c mystdio.c[jkl@host lib]$ lslibmyc.a  mylib     mymath.h  mystdio.c  mystdio.o  main.c    mymath.c  mymath.o  mystdio.h  roommate   
fPIC:产生位置无关码(position independent code)。这种代码可以在运行时被加载到内存中的任何位置,而不需要对代码本身进行修改。

3、将.o文件打包成动态库文件 

[jkl@host lib]$ gcc -shared *.o -o libmyc.so[jkl@host lib]$ lslibmyc.a   main.c  mymath.c  mymath.o   mystdio.h  roommate  libmyc.so  mylib   mymath.h  mystdio.c  mystdio.o  

1.2、怎么使用动态库 

1、先将动态库文件拷贝到lib目录下

[jkl@host lib]$ cp libmyc.so mylib/lib[jkl@host lib]$ tree mylibmylib|-- include|   |-- mymath.h|   `-- mystdio.h`-- lib    |-- libmyc.a    `-- libmyc.so2 directories, 4 files

2、 通过命令编译文件

[jkl@host roommate]$ gcc main.c -I mylib/include -L mylib/lib -lmyc[jkl@host roommate]$ lsa.out  log.txt  main.c  mylib[jkl@host roommate]$ ./a.out./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory[jkl@host roommate]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffde21da000)libmyc.so => not foundlibc.so.6 => /lib64/libc.so.6 (0x00007f4245348000)/lib64/ld-linux-x86-64.so.2 (0x00007f4245716000)

 没有找到这个动态库文件,原因是:动态库在程序运行的时候,要找到动态库加载并运行

为什么静态库没有找不到文件的问题?

编译期间,已经将库中的代码拷贝到我们的可执行程序内部了!加载和库没有关系了,这也是为什么静态库所占内存空间比动态库大很多的原因。

解决办法一

将动态库安装到系统中(不推荐)。

[jkl@host roommate]$ sudo cp mylib/lib/libmyc.so /lib64 # 将动态库文件拷贝到系统中,普通用户需要使用sudo提权[sudo] password for jkl: [jkl@host roommate]$ gcc main.c -I mylib/include -L mylib/lib -lmyc # 默认使用动态库编译[jkl@host roommate]$ lsa.out  log.txt  main.c  mylib[jkl@host roommate]$ ./a.out # 执行代码10 + 20  = 30[jkl@host roommate]$ ldd a.outlinux-vdso.so.1 =>  (0x00007fff79128000)libmyc.so => /lib64/libmyc.so (0x00007fdef1f1b000) # 我们拷贝的动态库libc.so.6 => /lib64/libc.so.6 (0x00007fdef1b4d000)/lib64/ld-linux-x86-64.so.2 (0x00007fdef211d000)[jkl@host roommate]$ file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=37f079df869cdf34f19759f0317a0da027a1973a, not stripped

删除拷贝的动态库文件 

[jkl@host roommate]$ sudo rm /lib64/libmyc.so # 删除动态库文件[jkl@host roommate]$ ll /lib/libmyc.so  # 查看前面拷贝的动态库文件,确认删除ls: cannot access /lib/libmyc.so: No such file or directory[jkl@host roommate]$ ./a.out # 删除之后就运行不了,不需要重新编译./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory

解决办法二

建立软链接。

[jkl@host roommate]$ sudo ln -s /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so /lib64/libmyc.so # 将自己的动态库文件软链接到系统的同名文件[jkl@host roommate]$ ll /lib64/libmyc.so # 查看软链接文件lrwxrwxrwx 1 root root 57 Sep 10 14:06 /lib64/libmyc.so -> /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so[jkl@host roommate]$ ./a.out # 运行程序10 + 20  = 30[jkl@host roommate]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffd94fc9000)libmyc.so => /lib64/libmyc.so (0x00007f31209de000)libc.so.6 => /lib64/libc.so.6 (0x00007f3120610000)/lib64/ld-linux-x86-64.so.2 (0x00007f3120be0000)

取消软链接

[jkl@host roommate]$ sudo unlink /lib64/libmyc.so # 取消软链接[jkl@host roommate]$ ll /lib64/libmyc.so # 查看软链接文件,没有该文件ls: cannot access /lib64/libmyc.so: No such file or directory[jkl@host roommate]$ ./a.out # 程序执行不了./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory

解决办法三

命令行导入环境变量(内存级别的,退出就没有该环境变量了)

[jkl@host roommate]$ LD_LIBRARY_PATH=$LD_LIBARY_PATH:/home/jkl/linux-learning/lib/roommate/mylib/lib[jkl@host roommate]$ echo $LD_LIBRARY_PATH:/home/jkl/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/jkl/linux-learning/lib/roommate/mylib/lib[jkl@host roommate]$ ./a.out10 + 20  = 30[jkl@host roommate]$ ldd[jkl@host roommate]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffe06fcf000)libmyc.so => /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so (0x00007f7dcb53e000)libc.so.6 => /lib64/libc.so.6 (0x00007f7dcb170000)/lib64/ld-linux-x86-64.so.2 (0x00007f7dcb740000)

退出xshell

[jkl@host roommate]$ echo $LD_LIBRARY_PATH:/home/jkl/.VimForCpp/vim/bundle/YCM.so/el7.x86_64[jkl@host roommate]$ ./a.out./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory

解决办法四

修改.bashrc配置文件,让环境变量永久生效。

1、编辑.bashrc文件

[jkl@host ~]$ vim .bashrc[jkl@host ~]$ source ~/.bashrc # 立即生效

注意:如果环境变量没有生效退出XShell重新登录即可。 

 2、执行代码

[jkl@host roommate]$ echo $LD_LIBRARY_PATH :/home/jkl/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/jkl/linux-learning/lib/roommate/mylib/lib[jkl@host roommate]$ ./a.out10 + 20  = 30[jkl@host roommate]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffcfdfe7000)libmyc.so => /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so (0x00007f638dac1000)libc.so.6 => /lib64/libc.so.6 (0x00007f638d6f3000)/lib64/ld-linux-x86-64.so.2 (0x00007f638dcc3000)

3、将路径从文件中删除。

[jkl@host ~]$ cat .bashrc# .bashrc# Source global definitionsif [ -f /etc/bashrc ]; then. /etc/bashrcfi# Uncomment the following line if you don't like systemctl's auto-paging feature:# export SYSTEMD_PAGER=# User specific aliases and functionsalias vim='/home/jkl/.VimForCpp/nvim'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/.VimForCpp/vim/bundle/YCM.so/el7.x86_64

解决办法五

/etc/ld.so.conf.d 新增动态库搜索的配置文件,ldconfig生效。

 1、在/etc/ld.so.conf.d 目录下新增一个.conf结尾的文件,内容为动态库文件所在目录(需要root权限)

[jkl@host ~]$ cd /etc/ld.so.conf.d # 进入目录[jkl@host ld.so.conf.d]$ lsbind-export-x86_64.conf  dyninst-x86_64.conf  kernel-3.10.0-1160.108.1.el7.x86_64.conf  mysql-x86_64.conf[jkl@host ld.so.conf.d]$ sudo touch mylib.conf # 创建文件需要提权[sudo] password for jkl: [jkl@host ld.so.conf.d]$ lsbind-export-x86_64.conf  dyninst-x86_64.conf  kernel-3.10.0-1160.108.1.el7.x86_64.conf  mylib.conf  mysql-x86_64.conf[jkl@host ld.so.conf.d]$ sudo vim mylib.conf[jkl@host ld.so.conf.d]$ sudo ldconfig # 让动态链接库为系统所共享

 2、执行代码

[jkl@host roommate]$ ./a.out10 + 20  = 30[jkl@host roommate]$ lddldd: missing file argumentsTry `ldd --help' for more information.[jkl@host roommate]$ ldd a.outlinux-vdso.so.1 =>  (0x00007fffacf78000)libmyc.so => /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so (0x00007f48d1437000)libc.so.6 => /lib64/libc.so.6 (0x00007f48d1069000)/lib64/ld-linux-x86-64.so.2 (0x00007f48d1639000)

动静态库总结

动静态库的最终意义还是提高开发效率。 

2、外部库使用

系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。
比如用来处理屏幕显示情况的函数(ncurses库)

#include <math.h>#include <stdio.h>int main(){  double x = pow(2.0, 3.0);  printf("The cubed is %f\n", x);  return 0;}

使用外部库链接 

[jkl@host lib]$ gcc -Wall calc.c -o calc -lm[jkl@host lib]$ ldd calclinux-vdso.so.1 =>  (0x00007ffdf00a1000)libm.so.6 => /lib64/libm.so.6 (0x00007fb17991b000)libc.so.6 => /lib64/libc.so.6 (0x00007fb17954d000)/lib64/ld-linux-x86-64.so.2 (0x00007fb179c1d000)[jkl@host lib]$ ./calcThe cubed is 8.000000

有链接到外部库。 

lm表示要链接libm.so或者libm.a库文件

库文件名称和引入库的名称

如:libc.so -> c库,去掉前缀lib,去掉后缀.so,.a

直接编译

[jkl@host lib]$ gcc calc.c[jkl@host lib]$ ./a.outThe cubed is 8.000000[jkl@host lib]$ ldd a.outlinux-vdso.so.1 =>  (0x00007fffb4359000)libc.so.6 => /lib64/libc.so.6 (0x00007f2081cb1000)/lib64/ld-linux-x86-64.so.2 (0x00007f208207f000)

可执行程序的结果是一样的,只是链接到的库有差别。 


点击全文阅读


本文链接:http://zhangshiyu.com/post/181398.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1