1 基础知识

变量是计算机系统用于保存可变值的数据类型,我们可以直接通过变量名称来提取到对应的变量值。

在Linux系统中,环境变量是用来定义系统运行环境的一些参数,比如每个用户不同的家目录(HOME)等。

值得一提的是,Linux 系统中环境变量的名称一般都是大写的,这是一种约定俗成的规范。

1.1 Linux环境变量详解

查看系统所有环境变量

env

查看单个环境变量值

echo $ENVNAME
# 例如,查看HOME
echo $HOME

设置环境变量的值

ENVNAME=value

使用 env 命令,我们可以查看当前系统所有的环境变量,使用 echo 命令,可以查看单个环境变量的值,直接使用 “环境变量名=值” 的形式即可以设置环境变量的值。

2 Linux动态库加载优先级

2.1 gcc编译程序时候查找动态库的顺序

  1. gcc编译时参数-L指定的路径

  2. 环境变量 LIBRARY_PATH

  3. /lib

  4. /usr/lib

2.2 Linux程序运行时查找动态库的顺序

  1. gcc 编译时指定的运行时库路径 -Wl,-rpath

  2. 环境变量 LIBRARY_PATH

  3. ldconfig 缓存 /etc/ld.so.cache

  4. /lib

  5. /usr/lib

3 Linux程序运行动态库设定方法

3.1 -Wl,-rpath

  • -Wl: 是编译器(gcc)选项,用于将后续的参数传递给传递给链接器(ld)。它允许你在编译和链接过程中向链接器传递额外的参数或选项,以控制链接的行为。这里就是传递 -rpath
  • -Wl,-rpath:使用冒号(:)来分隔多个路径,例如
    gcc -o test test.c -Wl,-rpath,/path1:/path2
    
  • -L:是编译时动态库所在目录

3.2 环境变量LD_LIBRARY_PATH

# 多个路径需要用冒号隔开,$表示取环境变量LD_LIBRARY_PATH的值
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/path

如果想要每次打开shell窗口,都可以自动设定该环境变量,在文件 ~/.bashrc 最后一行添加以上内容

运行 source ~/.bashrc 使其生效

3.3 /etc/ld.so.conf

` ldconfig `是一个动态链接库管理命令。主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式 lib.so),进而创建出动态装入程序(ld.so)所需的连接和缓存文件(默认缓冲文件是 /etc/ld.so.cache)。

/etc/ld.so.conf 文件和 /etc/ld.so.conf.d 目录中指定的库文件

3.1 /etc/ld.so.conf添加

用sudo权限在/etc/ld.so.conf文件最后新增一行动态库路径,比如写入/usr/local/lib。然后命令行运行sudo ldconfig

3.2 /etc/ld.so.conf.d目录添加

lieryang@lieryang-B760M-AORUS-ELITE-AX:/etc$ cat ld.so.conf
include /etc/ld.so.conf.d/*.conf

发现只有在 ld.so.conf.d 文件夹内,以 .conf 结尾的文件也会包含到其中。

例如:

lieryang@lieryang-B760M-AORUS-ELITE-AX:/etc/ld.so.conf.d$ sudo touch test.conf
lieryang@lieryang-B760M-AORUS-ELITE-AX:/etc/ld.so.conf.d$ sudo echo /usr/local/mylib/lib >> test.conf 

注意事项

  1. 往/lib和/usr/lib里面添加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调用ldconfig,更新缓存文件。
  2. 以上两个目录以外添加东西,需要将目录/usr/local/mylib/lib添加到/etc/ld.so.conf,然后调用ldconfig,更新缓存文件。

4 问题总结

4.1 符号链接不能找到问题

lieryang@lieryang-B760M-AORUS-ELITE-AX:~$ sudo ldconfig
[sudo] password for lieryang: 
/sbin/ldconfig.real: /lib/x86_64-linux-gnu/libavutil.so.56 is not a symbolic link

libavutil.so.56 应该是一个符号链接,但是 libavutil.so.56 是一个实体文件。

# 查看后发现 libavutil.so.56 是一个实体文件,貌似应该是 libavutil.so.56 是符号文件, libavutil.so是实体文件才正确(不过我们这里不这样修改)
lieryang@lieryang-B760M-AORUS-ELITE-AX:~$ ls -al /lib/x86_64-linux-gnu/libavutil.so*
lrwxrwxrwx 1 root root      15 10月 23 18:45 /lib/x86_64-linux-gnu/libavutil.so -> libavutil.so.56
-rwxr-xr-x 1 root root 1554824 10月 23 18:45 /lib/x86_64-linux-gnu/libavutil.so.56
-rw-r--r-- 1 root root  691088  5月 19  2022 /lib/x86_64-linux-gnu/libavutil.so.56.70.100
# 修改 libavutil.so.56 名称为 libavutil.56.so
lieryang@lieryang-B760M-AORUS-ELITE-AX:/lib/x86_64-linux-gnu$ sudo mv libavutil.so.56 libavutil.56.so
# 重新建立符号链接 libavutil.so.56 -> libavutil.56.so 
lieryang@lieryang-B760M-AORUS-ELITE-AX:/lib/x86_64-linux-gnu$ sudo ln -s libavutil.56.so libavutil.so.56

不清楚为什么??? libavutil.so.56 必须是符号文件,哪里决定的??

4.2 如何查看链接器ld默认搜索路径

ld --verbose | grep SEARCH_DIR

alt text