第1章 Linux系统编程入门:动态链接库的创建和使用

动态库的制作

一、命名规则

  • Linux : libxxx.so
    lib : 前缀(固定)
    xxx : 库的名字,自己起
    .so : 后缀(固定)
    在Linux下是一个可执行文件
  • windows:libxxx.dll

二、动态库的制作

  • gcc 得到 .o 文件,得到和位置无关的代码(具体原理暂时不分析,我也不清楚)
    gcc -c –fpic/-fPIC a.c b.c
  • gcc 得到动态库
    gcc -shared a.o b.o -o libcalc.so

动态库的基本工作原理

  • 静态库:GCC 进行链接时,会把静态库中代码打包到可执行程序中(也就是说编译成可执行程序后,就没静态库什么事了)
  • 动态库:GCC 进行链接时,动态库的代码不会被打包到可执行程序中(在进行链接时仅仅只是把基本的函数名称等文件信息放入其中,最终动态库需要在可执行程序运行的时候加载到内存)
  • 程序启动之后,动态库会被动态加载到内存中,通过 ldd (list dynamic dependencies)命令检查动态库依赖关系,说白了可以通过这个命令查看源程序中的动态库的情况,是否能被操作系统找到,并优先载入内存。

如何定位共享库文件呢?

这也是用到了动态库的源程序能否直接执行成功的关键,因为用到的动态库需要在程序执行的时候先一步载入内存,所以需要让操作系统知道它的存在路径。

而在Linux系统下,操作系统会根据一定步骤去寻找elf文件(Linux系统下的动态库都是elf格式的二进制文件),在Linux下有对应的动态载入器来获取该文件的绝对路径。对于elf格式的可执行程序,是 由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 ——> 环境变量 LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib 目录找到库文件后将其载入内存。

所以只要更改以上的加粗内容都可以让操作系统清楚动态链接库的存在位置,最常用的就是更改环境变量和etc目录的情况。

如何使用动态链接库?

生成可执行文件的方法和静态链接库的生成没有任何区别,但此时是无法正常运行这个可执行文件的。

很明显上述的程序执行时报了错,接下来需要我们把动态链接库的目录让操作系统清楚的知道,程序才能运行。

首先我们来看看这个程序的动态库依赖情况:

我们发现libcal.so的路径它找不到。

常用的两个解决方法:

法一:添加环境变量

添加LD_LIBRARY_PATH变量的值的命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ljb/linux/lesson2/library/lib 

查看变量对应的值的命令:

echo $LD_LIBRARY_PATH
  • 再次查看ldd命令发现已经能找到路径了

程序也能成功运行了:

但是问题来了,如果你重新再打开一个终端,你会发现它还是报错:

所以这样配置的环境变量只是临时的,我们需要用户级别或者系统级别的环境变量配置。

用户级别的环境变量配置:

进入.bashrc(根据不同的shell版本用不同rc文件配置,zsh则是.zshrc)然后在最后一行加入刚刚我们配置的环境变量即可。

加入完后需要进行更新:

. ~/.zshrc 或者 source ~/.zshrc

系统级别环境变量配置:

更改etc/profile目录即可

sudo vim /etc/profile #进入后在末尾加入环境变量即可

. /etc/profile #同样需要更新资源

法二:修改etc/ld.so.cache文件列表

注意:这个文件没法直接文本编辑的更改,因为都是二进制的数据,我们需要通过更改/etc/ld.so.conf进行间接的更改。(注意需要sudo)

sudo vim /etc/ld.so.conf#打开后在后面直接添加路径即可,不需要像添加环境变量那样
#更新方式也不一样,需要以下命令
sudo ldconfig

好了两种方法都讲完了。

Guess you like

Origin blog.csdn.net/m0_50945504/article/details/121738166