【Linux】库的制作与原理(1)

1. 什么是库

库是写好的现有的,成熟的,可以复⽤的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个⼈的代码都从零开始,因此库的存在意义非同寻常。
本质上来说库是⼀种可执⾏代码的⼆进制形式,可以被操作系统载⼊内存执行。库有两种:

bash 复制代码
• 静态库 .a[Linux]、.lib[windows]
• 动态库 .so[Linux]、.dll[windows]

2. 静态库

静态库(.a):程序在编译链接的时候把库的代码链接到可执行⽂件中,程序运行的时候将不再
需要静态库。
⼀个可执行程序可能⽤到许多的库,这些库运⾏有的是静态库,有的是动态库,而我们的编译默
认为动态链接库,只有在该库下找不到动态.so的时候才会采⽤同名静态库。我们也可以使⽤ gcc
的 -static 强转设置链接静态库。

编译当前目录所有的.c文件,将它们链接成一个单一的可执行文件

编译当前目录所有的.o文件,将它们链接成一个单一的可执行文件

将所有的.o文件打包形成一个静态库

ar 是 Unix/Linux 系统中的一个重要命令,全称是 "archive"(归档),主要作用是创建、修改和提取静态库(归档文件)

它最常见的用途是将多个目标文件(.o 文件)打包成一个后缀为 .a 的静态库文件,方便程序编译时链接使用。

  • r(replace):替换或添加文件到归档文件中

    • 如果指定的文件已存在于归档中,则替换它
    • 如果不存在,则添加到归档中
  • c(create):创建归档文件

    • 当指定的归档文件不存在时,自动创建一个新的归档文件
    • 如果不使用 c 选项,而归档文件又不存在,命令会报错
  • libmy.a : 静态库命名

    • lib :固定前缀,所有静态库都以 lib 开头,是系统识别静态库的标志;
    • my :自定义的库名称(如 mathutilsmyapp);
    • .a:固定后缀(archive 的缩写,意为 "归档文件"),表示该文件是静态库。

可以看到直接将usercode.c编译成usercode是找不到库的。因为系统会默认去 /lib/usr/lib 等标准目录找库。自定义库(如 mylibc.a)不在这些目录,所以编译器找不到。

  • -L. :指定库文件的搜索路径

    这里的 . 表示当前目录,-L 选项告诉 GCC 编译器:在链接阶段,除了系统默认的库目录外,还要到 -L 后面指定的路径(此处为当前目录)中查找需要的库文件。

  • -lmy :指定要链接的库名称
    lib 是 Linux 系统中库文件的默认前缀-lmy 实际上告诉 GCC 去链接名为 libmy.a(静态库)或 libmy.so(动态库)的库文件。编译器会根据搜索路径(包括 -L 指定的路径和系统默认路径)查找并链接这个库。

-I.:指定头文件的搜索路径

这里的 . 表示当前目录,-I 选项告诉 GCC 编译器:在编译阶段(预处理阶段),除了系统默认的头文件目录外,还要到 -I 后面指定的路径(此处为当前目录)中查找需要的头文件。

把头文件和库文件拷贝到系统指定的头文件和库文件目录下

将.h 和 .a进行打包:

-I 选项用于指定 头文件(header files)的搜索目录

3. 动态库

3.1 制作动态库:

  • -fPIC:生成位置无关代码(Position-Independent Code),用于创建可被多个程序共享的动态链接库(.so 文件),确保库代码在不同内存地址加载时能正确执行。
  • -shared: 告诉 gcc 编译器,要将输入的目标文件(.o 文件) 链接成一个共享库文件。共享库是一种可在运行时被多个程序同时使用的动态链接库,在 Linux 系统中,共享库文件的后缀通常是 .so

3.2 打包动态库:

cpp 复制代码
l: Makefile
  1 libmy.so:mystdio.o mystring.o
  2   gcc -shared -o $@ $^
  3 mystdio.o:mystdio.c
  4   gcc -fPIC -c $<
  5 mystring.o:mystring.c
  6   gcc -fPIC -c $<
  7 
  8 .PHONY:output
  9 output:
 10   mkdir -p lib/include
 11   mkdir -p lib/mylib
 12   cp -f *.h lib/include
 13   cp -f *.so lib/mylib
 14   tar czf lib.tgz lib
 15 
 16 .PHONY:clean
 17 clean:
 18   rm -rf *.o libmy.so lib lib.tgz                                                                                                 

3.3 编译运行程序:

静态库能直接运行,是因为链接时会将库中代码完整拷贝到可执行文件里,运行时不依赖外部文件。

动态库找不到,是因为链接时仅记录库的引用,运行时系统默认只在标准路径找库。若动态库在非标准路径(如这里的lib/mylib),未通过LD_LIBRARY_PATH等方式告知系统位置,就会找不到。

当系统运行可执行文件时找不到对应的动态链接库,主要有以下几种解决方法:

1. 拷贝至系统标准库目录 :将动态库文件(如 libmy.so)直接复制到系统默认搜索动态库的目录,比如 /lib/usr/lib 等。这样系统在运行程序时,能在这些标准目录中找到动态库。

2. 建立软链接

在系统的标准库目录(如 /lib/usr/lib)下,为动态库文件创建软链接。通过软链接,系统可以间接定位到实际的动态库文件,从而让程序能够加载到动态库。

3. 设置 LD_LIBRARY_PATH 环境变量

设置环境变量 :执行 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/user1/linux-learning/course/lesson14/ku/zhangsan/lib/mylib,把动态库 libmy.so 所在的目录 /home/user1/linux-learning/course/lesson14/ku/zhangsan/lib/mylib 添加到 LD_LIBRARY_PATH 中。LD_LIBRARY_PATH 是 Linux 系统中用于指定动态链接库搜索路径的环境变量,程序运行时会在该变量指定的路径里查找所需的动态库。

验证环境变量 :用 echo ${LD_LIBRARY_PATH} 查看,能看到刚添加的路径已在其中。

4. 配置 /etc/ld.so.conf.d/ :在 /etc/ld.so.conf.d/ 目录下创建一个以 .conf 为后缀的配置文件(例如 mylib.conf),在该文件中添加动态库所在的目录。然后运行 sudo ldconfig 命令,更新系统的动态链接库缓存。这样系统会将该目录纳入动态库的搜索范围,所有程序都能在该目录下查找动态库,这是一种较为持久且系统级的配置方法。

相关推荐
生涯にわたる学び2 小时前
关于之前知识的一些补充 02
linux·arm开发
汐汐咯2 小时前
linux上安装minconda
linux·运维·服务器
小波小波轩然大波2 小时前
Linux服务器配置(mariadb服务器)
linux·服务器·mariadb
忧郁的橙子.3 小时前
k8s 主节点重启后 从节点 get 异常
linux·运维·服务器
Raymond运维3 小时前
Apache介绍和安装
linux·运维·apache
半梦半醒*3 小时前
nginx的访问控制、用户认证、https
linux·运维·服务器·nginx·https·centos
Skrrapper4 小时前
ubuntu?centos?还是 redhat?Linux 系统选哪个?
linux·ubuntu·centos
进击的_鹏5 小时前
【Linux】权限
linux·服务器
ZhiqianXia5 小时前
Linux 内核开发 的核心知识点
linux