Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >动态库与静态库

动态库与静态库

作者头像
二肥是只大懒蓝猫
发布于 2023-03-30 06:36:14
发布于 2023-03-30 06:36:14
2.4K00
代码可运行
举报
文章被收录于专栏:热爱C嘎嘎热爱C嘎嘎
运行总次数:0
代码可运行

本文目标:

⭐认识动态静态库,学会结合gcc选项,制作动静态库⭐ ⭐了解动态库加载过程⭐

库的一些概念:

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。

动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。

在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)

动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

动静态库的本质:

(.o文件:二进制目标文件)

如果一个工程,被分成了头文件、和好几个工程项目,比如我们使用C语言实现一个简单的计算器,包含加减乘除,然后把加减乘除分别分开写,比如是Add.c一个工程项目,Sub.c一个工程项目等等,再使用main.c来调用它们。这样一来,就需要所有的工程项目的".o文件"链接起来。于是,随着工程项目越来越大,".o"文件也越来越多,于是聪明的工程师们就将这些".o"文件打包,变成一个库文件!因此,库的本质,就是一个文件,是包含了许多常用的".o"文件的库文件!

静态库

站在制作者的角度:生成静态库

生成静态库的方法,就是将所有的".o"文件打包,下面是演示的代码:

使用自动化构建工具Makefile将所有.o文件打包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   libmymath.a:my_add.o my_sub.o
       ar -rc $@ $^
   my_add.o:my_add.c
       gcc -c my_add.c -o my_add.o
   my_sub.o:my_sub.c
       gcc -c my_sub.c -o my_sub.o     


ar:archive,归档的意思,就像我们打包zip一样。    
-rc:rc表示(replace and create),意思是如果在我们的静态库文件libmymath.a里面,没有某个.o文件,比如没有add.o,那么就会create一个,添加进去。如果有了,就会替换掉。                                                                                                 

 make一下,最后就会形成我们需要的libmymath.a的文件,也就是生成了一个静态库!但此时,还不能发给用户去使用,因为里面并没有头文件。因此,我们需要在库文件里面,也添加头文件,并且把.o文件和头文件分别放在库文件里面不同的目录路径下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1 libmymath.a:my_add.o my_sub.o
  2     ar -rc $@ $^
  3 my_add.o:my_add.c
  4     gcc -c my_add.c -o my_add.o
  5 my_sub.o:my_sub.c
  6     gcc -c my_sub.c -o my_sub.o
  7 
  8 
  9 .PHONY:output
 10 output:
 11     mkdir -p mylib/include   //创建一个目录路径mylib,里面有include目录,用来存放头文件
 12     mkdir -p mylib/lib   //在mylib里,创建lib目录,用来存放库文件
 13     cp -f *.a mylib/lib   //将Makefile的当前路径下的所有.a的文件拷贝到lib里面
 14     cp -f *.h mylib/include  //将Mkafile的当前路径下的所有.h文件拷贝到include目录里面                                                                                                                    
 15                                        
 16 .PHONY:clean                           
 17 clean:                                 
 18     rm -f *.o libmymath.a   

 现在的库文件,就真正地形成了,然后接下来就是将库文件打包,交付就行了。

 站在使用者的角度:使用第三方静态库

指令:gcc main.c -L. -lmymath   其中的main.c就是用户的主函数的工程文件,-L 带上库路径,-l (小写的 L )带上库名     -I (大写的 i )带上头文件的路径 -L 指定库路径 -l 指定库名 -I 指定头文件路径 需要注意的是:带上的库名,注意要去掉头尾,即lib和.a/.so需要去掉,才是库名。

我们在平时用C语言和C++语言写代码的时候,并不需要指明库名称,就能使用C的库或C++的库,那是因为gcc或g++,本身就是用来写C/C++的,已经默认加上了库名了。

gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath

当然,测试目标文件生成后,静态库mylib,其它的所有的.c,.h,.o文件删掉,程序照样可以运行,因为这些文件,已经链接在目标文件里面了。

形成一个可执行程序,可能不仅仅只依赖一个库!而gcc的库默认是动态链接,但是当提供的是静态库时,并不能说gcc不会使用静态库,事实证明,不管是动态还是静态,都可以使用。因此,gcc默认动态库,是建议的意思,对于一个指定的库,是动态还是静态,取决于我们使用的库的什么库。如果在使用的若跟个库里面,只要有一个是动态库,那么,这个可执行程序就是动态链接的!

为了简化使用库的操作,我们可以将库安装在系统头文件里,安装的本质就是拷贝,也就是拷贝到系统头文件里面。

 sudo cp mylib/include/* /usr/include/    将库文件里面的头文件全部拷贝到到系统头文件中 sudo cp mylib/lib/*.a /lib64/     将libmymath.a静态库拷贝系统的库文件中

此时,就能简化使用的操作,当然,即使已经安装到系统里面了,但是gcc只会认识C语言库,第三方的库它能找到,但是不认识,因此在使用的时候,必须带上库名。

gcc main.c -lmymath

总结:制作者角度:生成静态库,就将需要的.o文件全部归档,并且头文件也一并带上,然后打包交付即可。使用者角度:在使用第三方库的时候,需要-L带上库的路径,-I头文件的路径和-l库的名称,注意库的名称是去掉lib和后缀之后的。不建议将自己写的第三方库安装到系统库中。

动态库

站在制作者的角度:生成动态库

动态库也是库,跟静态库差不多,也是.o文件归档,带上相应的头文件。其中的区别就是多加了一个选项:-fPIC。-fPIC的作用是在生成.o文件的时候,产生位置无关码,然后再多加了一个选项:-shared。-shared的意思是表示生成共享库格式。

 gcc -fPIC -c my_add.c my_sub.c   生成.o文件 gcc -shared -o libmymath.so my_add.o my_sub.o   归档

接下来的库还不能直接使用,因为需要带上头文件。因此我们创建一个目录,用来存放库和头文件,与生成静态库的步骤一致。

mkdir mylib  //创建新目录 mkdir mylib/include   //在mylib里面,创建include目录,存放头文件 mkdir mylib/lib        //在mylib里面,创建lib目录,存放libmymath.so动态库 mv libmymath.so mylib/lib/   //将libmymath.so动态库移到lib里面 cp *.h mylib/include/        //将头文件拷贝到include目录里面

至此,就能将mylib打包,交付!

站在使用者角度:使用第三方动态库

操作的方法与静态库的一样:

gcc -o mymath main.c -Imylib/include/ -Lmylib/lib/ -lmymath

可此时我们执行程序,会发现执行失败,理由是找不到这个动态库。

 前面我们在gcc编译的时候,虽然已经加上了路径和库的名字,但是那个是给gcc说的,是告诉gcc的,gcc才能把代码编译起来,编译完后,动态库就跟gcc没关系了。

然而现在是需要执行这个程序,对于动态库来说,这个可执行程序是需要找到它在哪,因此程序需要允许起来的时候,OS和shell也要知道库在哪!而此时我们写的库,没有在系统路径下,所以OS找不到。

解决找不到动态库的问题:

有时候OS和shell会在环境变量里面找,也会在系统路径里面找。因此:

方法一:在环境变量里面添加库:更改 LD_LIBRARY_PATH

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wjmhlh/lesson23/mylib/lib

此时,就可以正常运行了!但是这个方法有个缺点,自定义的环境变量添加到系统环境变量里,只在本次登录有效,等退出再登录的时候,就再次找不到了!

 方法二:拷贝到系统目录下,拷贝.so文件到系统共享库路径下, 一般指/usr/lib。这个方案跟静态库的一样,就不演示了,使用的时候记得带上-l库名。

方法三:配置文件:

在系统的路径里,有一个目录,/etc/ld.so.conf.d/,叫做conf,conf目录里面有一些文件,这些文件的作用是在进行动态库的搜索时,可以定义conf配置文件的方式,来让OS找到我们要的动态库。配置的方法很简单,只需要在conf里面创建一个目录,然后在目录里面写上我们的动态库的路径即可。接着使用指令:ldconfig,将conf目录更新一下,就完成啦!

步骤指令:

①    cd /etc/ld.so.conf.d/   进入conf系统目录 ②   sudo touch my_test    在conf里面创建一个目录 ③   sudo vim my_test.conf   进入创建的目录,然后将动态库的路径写入 ④   sudo ldconfig   更新目录 ⑤   cd - 回退到我们用户目录

这样,程序就可以正常执行了,并且永久有效。

方法四:软链接

通过软链接,类似于快捷方式,就可以了。

格式:ln -s 动态库的路径 动态库 ln -s /home/wjmhlh/lesson23/mylib/lib/libmymath.so libmymath.so 也可以建立在系统目录下: sudo ln -s /home/wjmhlh/lesson23/mylib/lib/libmymath.so  /lib64/libmymath.so

使用外部库:

系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况的函数(ncurses库)

 动态库的加载

静态库一般不考虑加载。一个程序在编译完成后,还没加载到内存时,就已经有了自己的代码区等,此时程序所用到的静态库被拷贝到代码区里面!此时的静态库的代码数据已经称为了这个程序的代码数据的一部分了,因此静态库不需要考虑加载问题。

动态库加载与访问加载过程:

与位置无关码:就是用特定的参照系来进行定位某一个人或物对应所处的位置,这种相对静止的方式就叫做与位置无关。

动态库不会像静态库一样,直接拷贝在可执行程序的代码区里面,而是动态库里指定的函数的地址,写入到可执行程序中,而这地址,暂且只需知道它是start:偏移地址,是起始地址+偏移地址的地址。

假设我们要访问C语言库中的printf函数,在可执行程序中有这个函数的偏移地址,但是这个地址属于外部地址,而这个printf函数是属于libc.so的,因此就能立马识别到这个库,然后操作系统暂时不执行代码,开始加载库,加载到内存,加载后,把这块内存通过页表,映射到虚拟空间的共享区,接着就会立马确定了这个库的起始地址!此时,因为我们要访问的printf所在的地址空间中,已经有了偏移量,然后可以去访问共享区,找到动态库的起始地址,然后拿着这个起始地址+偏移量,在共享区的libc.so这个库里面找到这个函数,然后调用,调用完之后返回代码区继续往后执行!

 理顺过程:在可执行程序里面遇到了printf,OS就识别到了printf是属于libc.so库的,然后加载库,拿到起始地址,接着拿着起始地址+偏移地址在共享区中的库里面找到这个函数调用,最后返回到代码区中继续执行下面的代码。

⭐本文结束!如果对您有帮助,可以点个赞和关注!下一篇预告:进程间通讯!⭐

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux之动态库和静态库
我们了解了动态库和静态库的相关概念,但是我们还是不理解库是个什么东西。 假设,我们做了一个小程序,只希望提供给用户小程序的功能,不希望暴露我们的源码。我们可以选择给用户提供我们的.o可重定位目标二进制文件(gcc -c 文件)与头文件。让用户使用我们提供的.o文件和.h文件进行链接即可。(在编译时,只需要把源文件编译成.o文件,再将其链接即可形成一个可执行程序,因此我们可以直接提供,o文件)。 文件add.c
摘星
2023/10/15
7800
Linux之动态库和静态库
【Linux】静态库和动态库
系统层面上有.和…硬链接指向目录。假设我们是超级用户,允许给目录建立硬链接,给根目录建立硬链接,从根目录开始查找,当查找硬链接的时候就是根目录,这时候递归式查找,形成了环路查找,最后导致软件无法正常进行查找工作!所以不允许普通用户给目录建立硬链接。
平凡的人1
2023/10/15
5750
【Linux】静态库和动态库
【Linux】动静态库
库分为 静态库(.a)和动态库(.so) 库的命名 以c++的库为例 输入 ls /lib64/libstdc++* 以lib开头要去除 库的真实名字为 stdc++
lovevivi
2023/05/10
2.5K0
【Linux】动静态库
【Linux】基础IO --- 软硬链接、acm时间、动静态库制作、动静态链接、动静态库加载原理…
2. 软链接文件soft_file.link有自己独立的inode,可以被当作独立文件看待。 而硬链接文件没有自己独立的inode,无论改变myfile.txt什么内容,hard_file.link都会随着一起改变,所以建立硬链接,实际上根本没有创建新文件,因为没有给硬链接分配独立的inode。
举杯邀明月
2023/04/12
3.7K0
【Linux】基础IO --- 软硬链接、acm时间、动静态库制作、动静态链接、动静态库加载原理…
【Linux系统IO】六、动静态库
​ 我们之前学 gcc 的时候也有接触过一点动静态库的知识,现在要把它单独拿出来讲,主要是因为我们后面肯定在自己开发的时候需要包装自己的库,此时就需要有动静态库的原理知识和使用知识!
利刃大大
2025/03/11
1070
【Linux系统IO】六、动静态库
静态链接库和动态链接库的区别
Linux下得库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。面对比一下两者:
狼啸风云
2019/11/03
8.6K0
【Linux】静态库和动态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
YoungMLet
2024/03/01
1K0
【Linux】静态库和动态库
Linux静态库与动态库加载
        关于库相比大家之前肯定使用过,比如C/C++里面的标准库,STL里面的各种库,我们在调用STL里的容器时都需要使用库,那么库到底是什么呢?
咬咬
2024/06/12
4270
Linux静态库与动态库加载
【Linux】动静态库
hello,大家好,今天我们继续学习Linux中的动静态库,我们将从不同的角度来学习如何使用,并如何制作一个可供他人使用的动静态库文件,并试着探究一下动态库加载问题。那我们就开始学习吧!!
破晓的历程
2024/06/24
1800
【Linux】动静态库
linux动态库和静态库的使用_静态库的使用
例如,用test1.c、test2.c、test3.c、test4.c以及main1.c形成可执行文件,我们需要先得到各个文件的目标文件test1.o、test2.o、test3.o、test4.o以及main1.o,然后再将这写目标文件链接起来,最终形成一个可执行程序。
全栈程序员站长
2022/11/11
4.9K0
详解动态库和静态库
在C、C++中我们使用过标准库,比如在使用strerror、vector、string等时,都只是调用了这些函数接口,这些都是需要具体的实现。
南桥
2024/06/03
2650
详解动态库和静态库
【Linux基础IO】Linux IO编程入门:揭秘动态库与静态库的秘密
前言:在Linux的浩瀚编程海洋中,IO(输入/输出)操作作为系统与外界交互的基石,其重要性不言而喻。无论是文件读写、网络通信还是设备驱动,都离不开IO操作的支撑。而在这个过程中,动静态库作为代码复用和模块化的重要手段,扮演着至关重要的角色。它们不仅简化了开发流程,提高了开发效率,还通过优化资源使用和减少编译时间等方式,为Linux程序的性能和可维护性保驾护航
Eternity._
2024/10/01
1360
【Linux基础IO】Linux IO编程入门:揭秘动态库与静态库的秘密
深入浅出动静态库
  当你在Linux系统上编写和运行程序时,动态库和静态库是两个非常重要的概念。它们不仅影响着程序的编译和执行效率,还直接关系到程序的可移植性和灵活性
用户11029129
2024/06/04
1570
深入浅出动静态库
Linux环境下静态库和动态库的实现
在软件开发中,库是非常重要的组成部分。它们包含了一组可复用的函数和代码片段,用于提高开发效率和代码质量。在Linux系统中,库分为静态库和动态库两种。本文将介绍它们的实现方式,结合C语言代码进行说明,并详细解释其原理和使用方法。
ahao
2025/01/05
1441
【Linux】从零开始认识动静态库 - 静态库
今天我们来学习动静态库。我们之前有没有使用过库呢??? 当然了: strerror strstr strcpy memset...等函数都要有具体的实现,那这个具体的实现在哪里呢???就是在我们的库中!
叫我龙翔
2024/05/11
2330
【Linux】从零开始认识动静态库 - 静态库
【Linux】动静态库(超详细)
💢 由于CentOS 8系统2021年12月31日已停止维护服务,CentOS 7系统将于2024年06月30日停止维护服务。CentOS官方不再提供CentOS 9及后续版本,不再支持新的软件和补丁更新。CentOS用户现有业务随时面临宕机和安全风险,并无法确保及时恢复。
IsLand1314
2024/11/19
1210
【Linux】动静态库(超详细)
【Linux】软硬连接与动静态库
硬连接不是一个独立的文件,因为它没有的独立的inode号,用的是目标文件的inode
用户11029103
2025/03/10
1070
【Linux】软硬连接与动静态库
【Linux】掌握库的艺术:我的动静态库封装之旅
在计算机编程中,库(Library)是一个预先编写的代码集合,包含了可以被其他程序调用的函数、类、变量和资源。库的主要目的是为了简化编程过程,提供常用功能的实现,促进代码重用,从而减少开发时间和提高软件的可靠性。
Yui_
2024/11/19
1080
【Linux】掌握库的艺术:我的动静态库封装之旅
linux 动态库 静态库_静态库里面包含动态库
那么这三个时间有什么作用呢? 我们在使用自动化构建工具Makefile时,如果连续make会发现:
全栈程序员站长
2022/11/10
7.6K0
linux 动态库 静态库_静态库里面包含动态库
动静态库:选择与应用的全方位指南
那么这样inode中一定有一个引用计数的变量用于记录这个inode编号有多少段映射关系。
绝活蛋炒饭
2024/12/16
950
动静态库:选择与应用的全方位指南
相关推荐
Linux之动态库和静态库
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验