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

linux下动静态库

什么是库

库是写好的现有的,成熟的,可以复⽤的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个⼈的代码都从零开始,因此库的存在意义⾮同寻常。

本质上来说库是⼀种可执⾏代码的⼆进制形式,可以被操作系统载⼊内存执⾏。库有两种:

  • 静态库 .a[Linux]、.lib[windows]
  • 动态库 .so[Linux]、.dll[windows]

静态库

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

ldd命令可以查看可执行程序所链接的库

基本命令:

ar -rc libname.a [要打包的.o文件]

ar (归档)能把一堆编译好的目标文件(.o)“捆” 成一个 .a 文件(静态库),方便程序在编译时一次性链接所有需要的代码。

r(replace):表示 “替换” 或 “添加” 目标文件。如果静态库中已有同名的 .o 文件,会用新的 .o 替换;如果库中没有该文件,就新增进去。

c(create):表示 “创建” 静态库。如果指定的 .a 文件不存在,-c 会强制创建它。

将库放到标准路径下

在我们生成库文件,在编译发现会报错这是为什么呢?

那是因为头文件和库都在标准路径下,把头文件放到usr/bin目录下或者在当前目录下,库文件要放到/lib64目录下。

但即使这样他还是会报错。因为对于库,OS会在默认标准路径即/lib64下查找,但是你要告诉他要找的库名字!

而libc.a却不用指定库名字(因为 libc.a 是 C 标准库的静态实现,GCC 等编译器会默认自动链接它,无需手动指定)

-l +库名字表示去标准路径寻找该库,但需要注意的是库的名字需要去掉.a或.so的后缀和lib前缀。

如果不在标准路径下就算指定了库名编译器也是找不到的。

库不放在标准路径下

-L +路径表示除了系统路径,也要去这个路径下找库

-I +路径表示除了系统路径,也要去这个路径下找头文件(就不演示了)

为了方便操作,我们可以创建一个makefile,内容可以这样写


%.o:%.c
gcc -c $<//.o文件的实现方法写哪里都可以,如果在执行某条命令时发现依赖文件没有生成,系统会自动检查makefile中的所有指令看有没有用于生成该依赖文件的
libmystdio.a:mystdio.o mystring.o
ar -rc $@ $^
.PHONY:clean
clean:
rm -rf *.a *.o stdc
.PHONY:output
output:
mkdir -p stdc/include//这需要先写mkdir,再写cp指令,这里是按照顺序执行的
mkdir -p stdc/lib
cp -rf *.c stdc/include
cp -rf *.a stdc/lib
tar -czf stdc.tgz stdc//打包压缩(便于传输共享)

动态库

  • 动态库(.so):程序在运⾏的时候才去链接动态库的代码,多个程序共享使⽤库的代码。
  • 动态库可以在多个程序间共享,所以动态链接使得可执⾏⽂件更⼩,节省了磁盘空间。操作系统采⽤虚拟内存机制允许物理内存中的⼀份动态库被要⽤到该库的所有进程共⽤,节省了内存和磁盘空间。

生成需要的.o文件

gcc -fPIC -c 源文件

-fPIC 是 GCC 编译器的一个关键选项,全称是 Position-Independent Code(位置无关代码),核心作用是让编译生成的二进制文件(如共享库 .so)能在内存的任意地址加载执行,而不依赖固定内存位置。

生成动态库

gcc -o name.so name.o -shared

在 GCC 编译中,-shared 是用于生成动态库(如 .so 文件)的关键选项,它的核心作用是让编译出的库可以被多个程序动态加载、共享使用,而不是像静态库那样被 “复制” 到可执行文件中。

libmystdio.so:mystdio.o mystring.o
gcc -o $@ $^ -shared
%.o:%.c
gcc -fPIC -c $<
.PHONY:clean
clean:
rm -rf *.so *.o stdc*
.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

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

头⽂件和库⽂件和源⽂件在同⼀个路径下

头⽂件和库⽂件有⾃⼰的独⽴路径

当库文件不在标准目录下时,生成了可执行文件后直接./a.out执行也会报错,ldd查看会发现我们a.out找不到库的路径  。

这是因为动态链接器(ld.so)在运行时默认只搜索系统标准目录(如 /lib/lib64/usr/lib 等),不会自动查找可执行文件所在目录或自定义路径下的动态库。

解决方法:

• 拷⻉ .so ⽂件到系统共享库路径下, ⼀般指 /usr/lib、/usr/local/lib、/lib64 或者开篇指明的库路径等

• 向系统共享库路径下建⽴同名软连接

• 更改环境变量: LD_LIBRARY_PATH

• ldconfig⽅案:配置/ etc/ld.so.conf.d/ ,ldconfig更新

动态库与静态库的联系与区别

区别:

  • 动态库中的.o文件形成时多了-fPIC选项,形成库文件时多了-shared选项.
  • 动态库形成的可执行程序时,编译时需要路径,运行时也需要路径,而静态库只有编译时需要路径.

联系:

  • 如果同时提供动态库和静态库,gcc默认使用动态库.
  • 如果指定要静态连接,gcc命令要带上-static选项.
  • 如果只有静态库,将使用静态连接,但程序整体不一定是静态连接的.
  • 如果只有动态库,只能使用动态连接,使用静态连接会报错.

动态库加载

上文主要解释了库是怎么形成的,怎么参与形成可执行文件;它们不运行时都是在磁盘中存储;

当程序运行时,它依赖的动态库是怎么加载到内存,或者说操作系统?

系统角度理解

程序的代码和数据,从磁盘到物理内存,再通过也页表映射加载到进程的代码区和数据区。此时进程需要动态库的代码和数据,不选择加载到进程的代码区和数据区 ,因为不一定只有一个进程需要此动态库,那么动态库的代码和数据就存在公共属性,应该通过页表映射加载到共享区!这样,进程调用库函数依旧在进程地址空间中!

其他问题:

1.库的加载逻辑问题,也就是一个库要不要加载,哪些库加载了?哪些没加载?

   这些都是由操作系统决定,目前不用具体了解怎么决定的。

2.加载的库需要被管理

   被加载的库存在数量多的情况,需要管理,操作系统依旧基于“先描述,再组织”的思想进行管理

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

相关文章:

  • iss服务器网站建设防止网站流量被刷
  • 【机器学习16】连续状态空间、深度Q网络DQN、经验回放、探索与利用
  • 网络传输协议的介绍,HTTP、SSE、WebSocket
  • 上海做网站公司有哪些北京网站建设公司哪家实惠
  • iOS 基于 Foundation Model 构建媒体流
  • Zabbix 6.0 基于 LNMP 架构完整部署教程(CentOS7)
  • 接口自动化测试----高并发抽奖系统
  • 用Python来学微积分31-定积分的概念与几何意义详解
  • 使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 23--数据驱动--参数化处理 Yaml 文件
  • 基于SpringBoot的公务员考试管理系统【题库组卷+考试练习】
  • Nginx 反向代理 HTTPS CDN 配置检查清单(避坑版)
  • 网站套餐到期是什么意思减压轻松网站开发
  • 常见的矩阵运算方法与应用
  • SQLite 3.51.0发布,新功能解读
  • 贺州网站推广网站设计报价是多少
  • 网站信息备案变更 哪里做seo工具是什么意思
  • 【TiDB 插入性能优化实战:从 5 秒到毫秒级的跨越】
  • Kubernetes Recreate 部署策略完整实战指南
  • 企业级Agent智能体(智能小秘)之LangGraph智能体
  • 外卖开源系统源码设计思路:商家、骑手、用户三端一体化方案
  • MySQL数据库基础操作:
  • 有什么网站可以做商业网站需要多少钱
  • 早教网站模板哈尔滨门户网站制作哪家好
  • 从入门到精通:OpenAI Prompt Engineering 与 Prompt Caching 实战详解
  • HGDB单机修改IP地址或主机名(含Linux和windows )
  • 重庆公司章程网上查询平台网站建设优化话术
  • 神奇的工作室最新网站设计网站怎么设计
  • WordPress站点添加ssl证书东莞网站设计排行榜
  • Nestjs框架: 高可用微服务架构实践之动态gRPC客户端切换与异常处理优化
  • Git 拉取代码冲突操作