当前位置: 首页 > news >正文

Linux:库制作与原理

目录

​编辑

1.什么是库

2.静态库

2.1静态库生成

2.2静态库使用

3.动态库

3.1动态库生成

3.2动态库使用

3.3库运行搜索路径

4.目标文件

5.ELF文件

6.ELF从形成到加载轮廓

6.1ELF形成可执行

6.2ELF可执行文件加载


1.什么是库

成熟的代码库是经过验证、可复用的现成解决方案。在实际开发中,任何程序都依赖于大量基础库的支持,开发者无需从零开始编写所有代码,这正是代码库的重要价值所在。

从根本上说,库是可直接执行的二进制代码文件,能够被操作系统加载到内存中运行。库主要分为两种类型:

• 静态库文件扩展名:

  • Linux平台:.a
  • Windows平台:.lib

• 动态库文件扩展名:

  • Linux平台:.so
  • Windows平台:.dll

2.静态库

• 静态库(.a):在编译链接阶段将库代码直接嵌入到可执行文件中,程序运行时不再依赖静态库文件。

• 一个可执行程序可能同时使用静态库和动态库。默认情况下,编译器优先链接动态库(.so),仅在找不到同名动态库时才会使用静态库。如需强制静态链接,可通过gcc的-static选项实现。

2.1静态库生成

//以下是makefile文件包含;libmystdio.a:my_stdio.o my_string.oar -rc $@ $^ (我们一般用此命令来进行静态库的打包)echo "build $^ to $@ ... done"%.o:%.cgcc -c $< (让所有源文件生成对应的目标文件)echo "compling $< to $@ ... done".PHONY:cleanclean:rm -rf *.a *.o stdc*echo "clean ... done".PHONY:outputoutput: (我们一般用这些命令将头文件和生成的静态库组织起来,然后给别人使用)mkdir -p stdc/includemkdir -p stdc/libcp -f *.h stdc/includecp -f *.a stdc/libtar -czf stdc.tgz stdcecho "output stdc ... done"

AR 是 GNU 归档工具,rc 参数表示"替换并创建"(replace and create)。通常我们使用 -rc 选项来进行静态库的打包操作。常用选项:

  • t:列出静态库中的文件
  • v:显示详细信息(verbose)

2.2静态库使用

编译选项说明

  • -L:指定库文件搜索路径
  • -I:指定头文件搜索路径
  • -l:指定链接的库名称

静态库特性

  • 程序编译链接后,即使删除静态库文件,生成的可执行文件仍能正常运行

库文件命名规则

  • 引用库时需去除前缀lib及后缀(如.so.a
    示例:libc.so → 链接时使用-lc

场景1:

将头文件和库文件安装到系统路径下(此时编译 main.c 只需使用 -l 参数)

 gcc main.c -lmystdio

场景2:

头文件、库文件与源文件位于同一目录

gcc main.c -L. -lmystdio

场景3:

头文件和库文件拥有各自的独立存储路径。

gcc main.c -I头⽂件路径 -L库⽂件路径 -lmystdio

3.动态库

• 动态库(.so):程序运行时才链接动态库代码,多个程序可共享调用同一库代码。

• 动态链接的可执行文件仅包含所用函数的入口地址表,而非外部函数的完整机器码。

• 程序运行前,操作系统会将动态库中的外部函数机器码从磁盘加载到内存,这一过程称为动态链接(dynamic linking)。

• 动态库可被多个程序共享,因此动态链接能显著减小可执行文件体积,节省磁盘空间。操作系统通过虚拟内存机制,使物理内存中的同一动态库可被多个进程共享,从而优化内存和磁盘空间利用率。

3.1动态库生成

//以下是makefile文件:
libmystdio.so:my_stdio.o my_string.o                                           gcc -o $@ $^ -shared  (我们一般生成动态库只需在编译器加上—shared)  
%.o:%.cgcc -fPIC -c $<    
.PHONY:clean    
clean:rm -rf *.so *.o stdc*    echo "clean ... done"    
.PHONY:output    
output:    mkdir -p stdc/include    mkdir -p stdc/lib    cp -f *.h stdc/include    cp -f *.so stdc/lib    tar -czf stdc.tgz stdc    echo "output stdc ... done"
  • shared: 生成共享库格式
  • fPIC: 生成位置无关代码 (Position Independent Code) (目的是代码可以被加载器加载到内存的任意位置都可以正确的执行)
  • 库名规则: 遵循 libxxx.so 命名规范

3.2动态库使用

 场景1:

将头文件和库文件安装到系统路径下

 gcc main.c -lmystdio

场景2:

头文件、库文件与源文件位于同一目录

gcc main.c -L. -lmystdio

场景3:

头文件和库文件拥有各自的独立存储路径。、

gcc main.c -I头⽂件路径 -L库⽂件路径 -lmystdio

3.3库运行搜索路径

ldd 可以查看可执行文件所依赖的库:

ldd 可执行文件
ldd a.out 
linux-vdso.so.1 =>  (0x00007fff4d396000)libmystdio.so => not foundlibc.so.6 => /lib64/libc.so.6 (0x00007fa2aef30000)/lib64/ld-linux-x86-64.so.2 (0x00007fa2af2fe000)

上图显示系统无法找到生成a.out可执行文件所需的库文件。

解决方法:

• 将.so文件复制到系统共享库目录中,常见路径包括/usr/lib、/usr/local/lib或/lib64等,也可根据项目需求存放到指定库路径

• 在系统共享库路径下创建同名符号链接

• 通过修改LD_LIBRARY_PATH环境变量来指定库文件路径

• 采用ldconfig方案:配置/etc/ld.so.conf.d/目录后执行ldconfig命令更新库缓存

4.目标文件

在Windows环境下,IDE通常将编译和链接这两个步骤封装得十分完善,开发者只需一键构建即可完成。然而,当遇到错误时,特别是链接阶段的问题,很多人往往感到束手无策。

让我们深入剖析编译和链接的全过程,以便更清晰地理解动静态库的工作原理。

简单来说,编译就是将程序源代码转换为CPU能够直接执行的机器代码的过程。

例如:假设有个源文件 hello.c,它简单地输出"helloworld!"并调用 run 函数。这个 run 函数定义在另一个源文件 code.c 中。此时我们可以使用 gcc -c 命令分别编译这两个源文件。

 $ gcc -c hello.c$ gcc -c code.c$ lscode.c  code.o  hello.c  hello.o

编译完成后会生成两个扩展名为.o的目标文件。需要注意的是,如果只修改了某个源文件,只需单独重新编译该文件即可,无需重新编译整个工程。目标文件采用ELF格式,这是一种二进制封装形式。

注意:

file 命令用于识别文件类型。

file 文件名

5.ELF文件

要深入理解编译链接的细节,我们首先需要认识ELF文件。实际上,以下四种文件都属于ELF格式:

  1. 可重定位文件(Relocatable File):即.o文件,包含可与其他目标文件链接生成可执行文件或共享目标文件的代码和数据。

  2. 可执行文件(Executable File):可直接运行的程序。

  3. 共享目标文件(Shared Object File):即.so文件,作为动态链接库使用。

  4. 内核转储文件(Core Dumps):记录进程执行上下文,用于调试和故障分析。

ELF文件由四个主要部分组成:

  1. ELF头(ELF Header):位于文件起始位置,描述文件的基本特征,并定位其他组成部分。

  2. 程序头表(Program Header Table):列出所有有效的段(segments)及其属性,包括每个段的起始位置、偏移量和长度等信息。

  3. 节头表(Section Header Table):描述文件中各个节(sections)的信息。

  4. (Sections):ELF文件的基本组成单元,存储特定类型的数据。例如:

    • 代码节存储可执行指令
    • 数据节存储全局变量和静态数据等

常见节区类型:

• 代码段(.text):存储程序的可执行指令,构成程序的核心运行逻辑。

• 数据段(.data):存放已初始化的全局变量及静态局部变量。

6.ELF从形成到加载轮廓

6.1ELF形成可执行

  • 步骤1:将多份 C/C++ 源代码编译为目标文件 (.o)
  • 步骤2:合并多个 .o 文件中的段

6.2ELF可执行文件加载

一个ELF文件包含多个不同的Section,在加载到内存时会将这些Section合并成Segment。

合并原则基于相同属性,例如:

  • 可读性
  • 可写性
  • 可执行性
  • 是否需要加载时申请内存空间

因此,具有相同属性的不同Section可能会被合并到同一个Segment中加载到内存。

这种合并方式在ELF文件生成时就已确定,具体的合并规则被记录在ELF的程序头表(Program Header Table)中。(本文就浅显讲解ELF,不过多讲解了)

http://www.dtcms.com/a/490244.html

相关文章:

  • SpringBoot集成测试
  • PDF Protector for mac PDF文档加密解密工具
  • 任务型与聊天型语音机器人有什么区别
  • 【具身智能】Gemini Robotics 1.5 深度解析:当机器人学会“思考”与“技能迁移”
  • 【机器人】激光雷达(LiDAR)核心原理:定位、测距与抗干扰
  • 机器人动作捕捉:光学 / 惯性 / 无标记点技术对比与工业 / RoboMaster / 高校场景适配
  • 有网站后台模板如何做数据库网站建设的方式有哪些内容
  • 在 Linux 平台上安装 64 位 JDK
  • Spring Boot配置属性:类型安全的最佳实践
  • prometheus暴露指标
  • RunnableParallel 操纵输入和输出
  • [双指针] 1. 力扣283.移动零
  • 【博客规划】关于我未来的研究方向……
  • python 列表浅拷贝 深拷贝
  • 网站如何做后台留言淘宝客网站一般用什么做的
  • 使用snmpsim与docker批量生成snmpd模拟服务
  • 燕之屋(1497.HK)燕窝肽260万单场售罄,科技重塑传统
  • 【动态规划】数位DP的原理、模板(封装类)
  • 神经网络中的批归一化(BatchNorm)
  • 最新版本组件的docker下载-nacos-Rabbitmq-redis
  • 互素最多:任意五个整数互素的巧妙构造
  • 博客网站大全上海专业网站建设价格
  • Apache换行解析 文件上传漏洞复现:原理详解+环境搭建+渗透实践(CVE-2017-15715 vulhub)
  • 自动伸缩:K8s Cluster Autoscaler,节点池配置技巧?
  • 网站制作的预算网站建设著作权
  • 性能优化之前端与服务端中的 Gzip 压缩全解析
  • 【Day 77】Linux-iptables防火墙
  • GitHub 热榜项目 - 日榜(2025-10-16)
  • 爬虫汇总与实战
  • 哪个网站做网销更好python怎么做网站