Linux下的库(静态与动态)原理与制作

程序的编译过程

程序的编译过程是将源代码转换为可执行文件的一系列步骤。这个过程通常包括预处理、编译、汇编和链接等阶段

 

1. 预处理(Preprocessing)

  • 预处理器(cpp)处理源代码文件中的预处理指令,如#include#define
  • 它展开宏定义,包含头文件,并删除注释。
  • 输出是经过预处理的源代码,通常是一个.i文件。

2. 编译(Compilation)

  • 编译器(如gccclang)将预处理后的源代码转换为汇编语言。
  • 编译器进行语法检查、语义分析和优化。
  • 输出是汇编代码,通常是一个.s文件。

3. 汇编(Assembly)

  • 汇编器(如as)将汇编语言转换为机器代码。
  • 它将汇编指令转换为二进制形式的指令。
  • 输出是目标文件,通常是一个.o文件。

4. 链接(Linking)

  • 链接器(如ld)将一个或多个目标文件与库文件链接在一起,生成可执行文件。
  • 链接器解析外部引用,将库中的代码和数据合并到最终的可执行文件中。
  • 输出是可执行文件,通常没有扩展名或有特定平台的扩展名(如Linux下的.out)。

5. 库的创建(可选步骤)

  • 编译过程中可能会创建静态库(.a)或动态库(.so)。
  • 静态库在链接时被复制到可执行文件中。
  • 动态库在程序运行时被加载。

库的概念

库(Library)是计算机编程中一个重要的概念,它指的是一组预先编写好的代码,这些代码可以是函数、类、变量等,用于实现特定的功能或服务。库的使用可以提高开发效率,促进代码复用,降低编程难度,并帮助开发者避免重复发明轮子

在Linux系统中,库(Library)主要分为两种类型:静态库和动态库(共享库)

文件扩展名:

  • 静态库(Static Library, .a 或 .lib)

  • 在Linux系统中,静态库是一种编译时链接的库,它们在程序编译阶段被整合到最终生成的可执行文件中
  • 特点:

  • 整合性:静态库在编译时被整合到可执行文件中,因此可执行文件包含了所有需要的库代码。
  • 大小:由于静态库的代码被整合到可执行文件中,这可能导致可执行文件的体积增大。
  • 性能:静态链接的程序在运行时不需要加载额外的库文件,这可能带来轻微的性能提升。
  • 兼容性:静态库可以提高程序的兼容性,因为所有依赖都包含在可执行文件中,不依赖于系统上的库版本。
  • 静态库通常具有.a文件扩展名。

优点:

  • 兼容性好:不依赖于外部库文件,适合在不同环境中运行。
  • 性能:由于所有依赖都包含在内,可能减少运行时的加载时间

缺点:

  • 可执行文件体积大:包含所有库代码,导致文件膨胀。
  • 更新不便:库更新需要重新编译所有依赖程序

使用场景:

  • 静态库:适合嵌入式系统、不需要频繁更新的应用程序,或者在没有网络连接的环境中分发程序。

创建静态库:

文件扩展名:

优点:

缺点:

  • 编译源代码为对象文件

  • 首先,你需要将源代码编译成对象文件(通常是.o文件)。这可以通过编译器(如gcc)完成,使用-c标志来指示编译器只进行编译,不进行链接。

    gcc -c source_file.c -o source_file.o
  • 创建静态库: 使用ar命令来创建静态库。ar是归档器,用于创建、修改或从静态库中提取文件。

    ar rcs liblibrary_name.a object_file1.o object_file2.o ...
    • r:将文件添加到库中,如果库不存在则创建它。
    • c:创建库时不输出控制信息。
    • s:创建索引,这可以加快从库中提取文件的速度。

    例如,如果你有两个对象文件file1.ofile2.o,你可以这样创建库:

    ar rcs libmylib.a file1.o file2.o
  • 管理静态库

    • 查看库详细内容:使用ar -v 可以列出库中所有对象文件详细信息
    • ar -v libmylib.a
    • 查看库内容:使用ar -t可以列出库中的所有对象文件。
      ar -t libmylib.a
    • 从库中提取文件:使用ar -x可以提取库中的文件。
      ar -x libmylib.a file1.o
    • 删除库中的文件:使用ar -d可以删除库中的文件。
      ar -d libmylib.a file1.o
  • 使用静态库

  • 我们在使用静态库进行编译链接时,需要指定头文件的所在路径,库文件的所在路径以及所要调用的库名称

  • -I(大写i):指定头文件所在路径。

  • -L:指定库文件所在路径。

  • -l(小写l):指明需要链接库文件路径下的哪一个库

    gcc -o my_program my_program.c -L/path/to/library -lmylib

    这里-L指定库文件的搜索路径,-l指定要链接的库(不包括前缀lib和后缀.a

  • 链接器标志:可以使用-static标志来强制链接器链接静态库,忽略对动态库的链接请求。

  • gcc -static -o my_program my_program.c /path/to/libmylib.a
  • 动态库(Dynamic Link Library, .so 或 .dll)

  • Linux下的动态库(Dynamic Libraries)提供了一种在程序运行时才加载库的方法,与静态库相比,动态库具有一些不同的特性和使用方式

    特点:

  • 运行时链接:动态库在程序启动时或运行过程中被加载,而不是在编译时。
  • 共享性:多个程序可以同时使用同一个动态库,节省内存和磁盘空间。
  • 更新方便:库的更新只需要替换动态库文件,无需重新编译链接使用该库的程序。
  • 版本控制:可以有多个版本的动态库共存,程序可以通过链接时指定的版本号来加载特定版本的库。
  • 动态库通常具有.so(Shared Object)文件扩展名。
  • 节省空间:多个程序共享同一份库文件,减少磁盘占用
  • 易于更新:库的更新只需替换文件,无需重新编译程序。
  • 更好的兼容性:可以为不同的程序提供不同版本的库。
  • 依赖性:程序运行时需要动态库的存在,如果库文件被删除或更新,可能会影响程序的正常运行。
  • 启动速度:可能比静态库稍慢,因为需要在运行时解析和加载库。

使用场景:

动态库:适合需要频繁更新的应用程序,或者在有网络连接的环境中,可以方便地下载和更新库

创建动态库:

  • 编写源代码: 首先,你需要编写源代码,定义你想要在动态库中共享的函数和全局变量。

  • 编译源代码为对象文件: 使用编译器(如gcc)编译源代码为对象文件。确保使用-fPIC(Position Independent Code)标志,这样生成的对象文件可以在共享库中使用。

    gcc -fPIC -c source_file.c -o source_file.o
  • -fPIC:作用是告知编译器生成位置无关代码(编译产生的代码没有绝对位置,只有相对位置);从而可以在任意地方调用生成的动态库

  • 创建动态库: 使用编译器(带有-shared标志)或ld命令来创建动态库。对于gcc,可以这样

  • -shared:Linux在gcc编译时加上 -shared 参数时,目的是使源码编译成动态库 .so 文件

    gcc -shared -o libmylib.so source_file.o

    或者使用ld命令:

    ld -shared -o libmylib.so source_file.o
  • 安装动态库: 将生成的动态库文件libmylib.so复制到系统的库目录中,如/usr/lib/usr/local/lib。你可能需要管理员权限来执行此操作。

    sudo cp libmylib.so /usr/local/lib
  • 更新动态链接器的配置: 使用ldconfig命令来更新动态链接器的配置,确保系统知道新安装的库的位置。

    sudo ldconfig
  • 编写链接脚本: 如果需要,可以为动态库创建一个链接脚本(.map文件),这有助于调试和分析。

  • 使用动态库: 在编译需要使用动态库的程序时,使用-L标志指定库的路径,使用-l标志链接库(不包括前缀lib和后缀.so)。

    gcc -o my_program my_program.c -L/usr/local/lib -lmylib
  • 设置环境变量(如果库不在标准库路径中): 如果动态库不在标准的库搜索路径中,你可能需要设置LD_LIBRARY_PATH环境变量,以便运行时可以找到库。

    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值