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

Linux动静态库以及动静态链接

静态库

ar 是 gnu 归档⼯具(打包), rc 表⽰ (replace and create)

打包成静态库: ar -rc libXXX.a *.o

// Makefile libmystdio.a:my_stdio.o my_string.o @ar -rc $@ $^ %.o:%.c @gcc -c $< .PHONY:clean clean: @rm -rf *.a *.o stdc* .PHONY:output output: @mkdir -p stdc/include @mkdir -p stdc/lib @cp -f *.h stdc/include @cp -f *.a stdc/lib @tar -czf stdc.tgz stdc

在 Makefile 中,命令前的 @ 是 静默执行标记,核心作用是:隐藏命令本身的输出,只显示命令执行后的结果(或自定义 echo 提示)

用法

效果

适用场景

命令前加 @

隐藏命令本身,只显示执行结果/echo提示

绝大多数构建/清理/打包命令

命令前不加 @

显示命令本身 + 执行结果

调试 Makefile 时(查看实际执行的命令)

ar -tv libmystdio.a

• t: 列出静态库中的⽂件

• v:verbose 详细信息

静态库的使用

程序中使用到库的内容时,需要将库进行链接。

Linux查找库的时候只会区lib64路径下去查。其他路径需要加路径

// 场景1:头⽂件和库⽂件安装到系统路径下 $ gcc main.c -l库名字 // 场景2:头⽂件和库⽂件和我们⾃⼰的源⽂件在同⼀个路径下 $ gcc main.c -L. -l库名字 // 场景3:头⽂件和库⽂件有⾃⼰的独⽴路径 $ gcc main.c -I头⽂件路径 -L库⽂件路径 -lmymath

• -L: 指定库路径

• -I: 指定头⽂件搜索路径

• -l: 指定库名

• 测试⽬标⽂件⽣成后,静态库删掉,程序照样可以运⾏

• 关于 -static 选项,稍后介绍

• 库⽂件名称和引⼊库的名称:去掉前缀 lib ,去掉后缀 .so ,.a ,如: libc.so -> c

gcc专门编译C语言,默认认识C标准库,所以不用显示使用-l。gcc默认区/lib64下查找库,所以标准库不用-L。

库不可以包含main函数!!

我给别人提供一个库,要提供: 1. .a库文件 2. .h头文件(你的库的使用手册)

使用别人的库: (在使用任何三方库时必须使用-l)

  1. 可以将头文件拷贝到/usr/include/下,库文件拷贝到/lib64/下。这就是安装的过程。

      此时,在使用时,必须使用-l指明使用的是哪一个库。

    1. 使用选项-L -I -l指明条件,来使用静态库。头文件在预处理阶段就需要。

    2. 也可以在/lib64/下,与别人的库进行软链接。库文件拷贝到/lib64/下。使用-l找到别人的库

    动态库

    链接时,要使用-shared

    生成.o文件时,要是用fPIC

    // Makefile libmystdio.so:my_stdio.o my_string.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

    • shared:表⽰⽣成共享库格式

    • fPIC:产⽣位置⽆关码(positionindependentcode)

    • 库名规则:libxxx.so

    1. 形成动态库,不使用ar,而是使用gcc,g++。可以知道,默认形成的是动态库,形成静态库要使用附加命令。

    动态库的使用

    库的名字要去掉前缀和后缀

    ldd libXXX.so // 查看库或者可执⾏程序的依赖

    // 场景1:头⽂件和库⽂件安装到系统路径下 $ gcc main.c -l库文件名 // 场景2:头⽂件和库⽂件和我们⾃⼰的源⽂件在同⼀个路径下 $ gcc main.c -L. -l库文件名 // 从左到右搜索-L指定的⽬录 // 场景3:头⽂件和库⽂件有⾃⼰的独⽴路径 $ gcc main.c -I头⽂件路径 -L库⽂件路径 -l库文件名

    只使用gcc main.c -I头⽂件路径 -L库⽂件路径 -lmymath时,执行可执行程序会有找不到库的情况。

    这一步,是告诉了gcc我的库信息,是给编译器说的

    执行可执行程序的时候,会有找不到库的情况。这时是操作系统(加载器)找不到库。

    使用静态库的时候没这个问题,是由于静态库当中的方法,拷贝到了我的程序内部。程序运行,就不需要库了。

    动态库加载时的查找问题(运行时的查找问题)
    1. 将库文件拷贝到/lib64路径下

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

    1. 将库文件,在/lib64/下的文件中,建立软链接(向系统共享库路径下建⽴同名软连接)

    ln -s 路径 /lib64/lib库名.so

    1 2方法可以认为本质是一样的。

    1. 更改环境变量: LD_LIBRARY_PATH

    动态搜索路径除了搜索/lib64还会在该环境变量中寻找。将库的路径导入其中。

    LD_LIBRARY_PATH = $ LD_LIBRARY_PATH + 路径

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

    [root@localhost linux]# cat /etc/ld.so.conf.d/bit.conf /root/tools/linux [root@localhost linux]# ldconfig // 要⽣效,这⾥要执⾏ldconfig,重新加载库搜索路径

    在/etc/ld.so.conf.d/下新建文件,将你的库的路径拷贝进去。再执行ldconfig命令

    静态链接(Static Linking)

    1. 原理

    静态链接在**编译阶段**将所有依赖的库代码复制到最终的可执行文件中。

    • 使用的库文件:.a(静态库)

    • 链接器:ld(由gcc调用)

      2. 示例

      gcc -c main.c -o main.o gcc -c math.c -o math.o ar rcs libmath.a math.o # 创建静态库 gcc main.o -L. -lmath -o main_static

      • -L.:指定库搜索路径为当前目录

      • -lmath:链接libmath.a

        3. 特点

        优点

        缺点

        可执行文件独立运行,无外部依赖

        文件体积大

        启动速度快(无需运行时加载)

        库更新需重新编译所有程序

        部署简单(单文件分发)

        内存浪费(多程序重复加载相同库)


        三、动态链接(Dynamic Linking)

        1. 原理

        动态链接在**程序运行时才加载所需的共享库(.so)**,由**动态链接器(ld-linux.so)**完成。

        • 使用的库文件:.so(共享库)

        • 链接器:ld(生成部分链接的可执行文件)

        • 运行时加载器:ld-linux.so

          2. 示例

          gcc -fPIC -c math.c -o math.o # 生成位置无关代码 gcc -shared -o libmath.so math.o # 创建共享库 gcc main.c -L. -lmath -o main_dynamic # 编译时链接(仅记录依赖)

          运行时必须设置库路径:

          export LD_LIBRARY_PATH=. ./main_dynamic

          3. 特点

          优点

          缺点

          可执行文件体积小

          依赖外部.so文件,部署复杂

          多程序共享内存中的同一份库,节省内存

          启动时有轻微加载开销

          库更新无需重新编译程序(接口兼容)

          可能出现“依赖地狱”或版本冲突


          四、动静态链接对比总结

          特性

          静态链接

          动态链接

          链接时机

          编译时

          运行时

          可执行文件大小

          大(库代码被复制)

          小(仅记录依赖)

          内存使用

          每个进程独立加载库

          多进程共享一份库

          库更新

          需重新编译程序

          替换.so即可(接口兼容)

          运行依赖

          依赖.so存在且路径正确

          典型用途

          嵌入式、独立工具

          桌面系统、共享服务

          • 工具推荐

            • ldd:查看依赖的共享库

            • nm:查看符号表

            • objdump:反汇编目标文件

            • readelf:查看ELF文件结构

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

          相关文章:

        • 一个关于python编程小白日记
        • 自己做一个外贸网站怎么样沪上装修排名前十有哪些品牌
        • 环保HJ212-2017协议Java代码解析
        • 专业零基础网站建设教学深圳极速网站建设定制
        • 黑马点评学习笔记10(优惠券秒杀下单优化(分布式锁的优化,Lua脚本))
        • 单页面网站有哪些内容吗电子商务就业岗位
        • 亚马逊云科技 Amazon Bedrock 持续壮大模型阵营:Qwen3 和 DeepSeek-V3.1 重磅上线
        • 同一个空间可以做两个网站么wordpress建设购物网站
        • 小县城做网站福田做商城网站建设多少钱
        • 东莞网站制作方案定制无锡网站制作哪家服务好
        • 做的的网站怎样上传如何做网站关键字优化
        • 【OpenCV + VS】图像像素的加减乘除操作
        • 那里可以做网站的吗wordpress修改文章链接
        • [Java EE] 多线程 -- 初阶(2)
        • 蓝牙钥匙 第89次 蓝牙钥匙未来发展趋势篇:与汽车电子架构演进深度融合
        • 网站建设解析2345网址导航开创中国
        • 营销型网站模版vi设计的目的
        • U++工程提取二进制工程
        • Zabbix告警配置全攻略:邮件+钉钉双保险
        • qq钓鱼网站制作微盟集团
        • 中国人做跨电商有什么网站自建冷库费用
        • 03|Langgraph | 从入门到实战 | 进阶篇 | 持久化
        • 如何将网站挂载域名网站建设的定位是什么意思
        • 知识管理工具sward上手指南:安装、配置与入门
        • 在Vivado中添加HLS IP后只显示路径无法显示可例化的IP核解决方式
        • 二分查找专题(十):“Z字形”的降维!当二分查找“失效”时
        • 响应式网站源码.net互联网行业的开发网站
        • Windows10 使用 dynv6 + ddns-go 实现 IPv6 固定域名远程访问指南
        • 如何自己做彩票网站免费自动回收的传奇手游
        • 教育培训网站建站网络营销是以什么为中心