首页 > 系统相关 >Linux下的库(静态与动态)原理与制作

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

时间:2024-08-19 12:54:59浏览次数:8  
标签:文件 静态 编译 ar 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

标签:文件,静态,编译,ar,Linux,动态,链接
From: https://blog.csdn.net/2301_79695216/article/details/141190231

相关文章

  • Java轻松实现跨平台(Windows、Linux)多协议(Twain、Sane)的Web扫描
     由于项目需要,开发在Windows下与Linux下扫描功能,Linux主要是信创的两个系统(UOS、麒麟),研究了一下发现,Windows使用Twain协议与扫描仪通讯,Linux使用的是Sane协议与扫描仪通讯,找到Twain协议和Sane协议的标准文档,英文的,都有大几百页,项目一个月内要求上线,明显没时间慢慢研究,于......
  • Day34 动态规划Part2
    目录任务62.不同路径思路63.不同路径II思路343.整数拆分思路96.不同的二叉搜索树思路任务62.不同路径一个机器人位于一个mxn网格的左上角(起始点在下图中标记为“Start”)。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finis......
  • linux 安装python
    1、先查看系统python所在位置[root@localhost~]#whereispythonpython:/usr/bin/python/usr/bin/python2.7/usr/lib/python2.7/usr/lib64/python2.7/etc/python/usr/include/python2.7可确认系统原python环境在/usr/bin/下。2、进入/usr/bin/cd/usr/bin/3、先安......
  • 【JavaSec】类的动态加载初探
    0x02类的动态加载文章目录0x02类的动态加载什么是类加载?动态类加载方法:类加载:继承关系:调用关系:下面尝试使用URLClassLoader进行尝试http协议:jar协议:http读取方法:file读取方法:使用defineClass类加载方法Unsafe类加载什么是类加载?即虚拟机加载.class文件在......
  • 【~Linux系统性能调优技巧~】
    ......
  • 【Linux入门】DHCP与FTP原理及其配置实例
    文章目录DHCP原理一、DHCP概述二、DHCP的工作原理三、DHCP的分配方式四、DHCP的租约五、DHCP的应用场景FTP原理一、FTP概述二、FTP的工作原理三、FTP的连接模式四、FTP的应用配置实例DHCP配置实例DHCP服务器配置(CentOS7)1.环境准备2.安装DHCP服务3.配置网络接口4.......
  • visual studio当中动态库和静态库的联系
    一、为什么要写这篇博客公司需要调用MNN框架编译之后的动态库和静态库文件来在另外一台没有编译过MNN框架上的机器运行对应的程序,比如说人体关键点检测之类的程序,这个时候了解静态库和动态库的关系就很有必要了。二、现代编译器编译流程源代码(sourcecode)→预处理器(preprocess......
  • Linux安装nginx1.26.2
    第一步:去官网下载指定的版本http://nginx.org/en/download.html第二步:解压压缩包:tar-zxvf  ......tar.gz第三步:编译nginx ./configure如果出现报错:./configure:error:theHTTPgzipmodulerequiresthezliblibrary.Youcaneitherdisablethemodulebyusing--......
  • Linux C++ 开发4 - 入门makefile一篇文章就够了
    1.make和Makefile1.1.什么是make?1.2.什么是Makefile?1.3.make与Makefile的关系2.Makefile的语法2.1.基本语法2.2.变量2.3.伪目标2.4.模式规则2.5.自动变量2.6.条件判断3.示例演示3.1.编译HelloWorld程序3.2.编译多文件项目3.2.1.项目......
  • python subprocess 执行Linux指令
    一、subprocess模块1、概述subprocess模块首先推荐使用的是它的run方法subprocess.run(),更高级的用法可以直接使用Popen接口subprocess.Popen()。2、优点安全性:与os.system相比,subprocess避免了shell注入攻击的风险。灵活性:subprocess可以与子进程的stdin、stdout和std......