Loading [MathJax]/jax/output/HTML-CSS/jax.js

解锁动静态库的神秘力量1:从代码片段到高效程序的蜕变

简介: 解锁动静态库的神秘力量1:从代码片段到高效程序的蜕变

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

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

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

也可以理解为.o系列文件集合打包;那么为啥需要库呢?

因为如果有多个.c文件或者很多都要复用这些,那么总是把它们一同编译就显得有点冗余了;因此不妨使用库。

假设没有库,对于一堆维.c文件我们就直接gcc一步处理成可执行程序,然后运行(. h必须要在当前目录否则找不到) :

下面我们来以一些测试代码带大家进行讲解工作:

1.1静态库的形成与使用:
下面我们从这两方面带大家理解静态库:

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

这里静态库是直接拷贝到可执行程序中,gcc找到后完成编译,程序就可以跑,不需要运行exe时系统再去找库,但是动态库需典 。

说白了就是静态库会把对应的那一堆.o文件拷贝进可执行文件(这里对于动态库就不行了,后面我们细讲)。

其次就是,我们静态库要有lib和以.a后缀,然而库名是去掉这些。

下面形成静态库需要这几步:

1·把全部.c文件编译成.o。

2·把.o文件都打包生成静态库。

3·使用静态库与目标文件链接形成可执行程序。

这样我们就生成了.o文件。

完成静态库的形成。

使用静态库去和其他文件链接:

这样就可以跑起来了:

其实也是非常简单的。

1.2动态库的形成与使用:
步骤和上面静态库的大差不大,只是有些地方需要改动一下:

这里的-fPIC也是不可少的:

形成动态库(注意这里库名后缀改成了so,此外还多加了-shared):

接下来我们就去链接了:

但是生成的可执行程序p不能运行?

下面我们来查看一下可执行程序的动态链接情况:

这里发现所要动态链接的动态库无法找到,为什么呢?
GCC!=系统;静态库,系统可以从EXE中找到但是动态库找不到 。

这是因为动态库并没有像静态库那样拷贝进p文件;而是动态连接;链接的时候只是告诉gcc了这个库的位置;而运行的时候是系统干的,它不知道动态库位詈。

那就引出了我们下面的工作,就是去帮助系统运行可执行文件的时候找到动态库。

二·系统如何查找动态库 :
下面我们分四中方法来完成帮助系统寻找工作:

2.1.拷贝到系统lib库:
这里我们首先要知道,系统在运行可执行文件的时候先去lib库内看看有没有这个库:

下面我们就查看一下系统的lib库:

找到后我们把当前路径的动态库文件拷贝进去:

然后我们再次运行:

这里一般我们安装程序等,系统都会采用这种方法把动态库装到lib库内。

2.2建立软链接:
之前博主出了一片Ext2文件系统的文章里面会对软硬链接有所介绍,不懂的朋友们可以去看一下,传送门:Ext2 文件系统:数字世界的基石,深度解码超时空存储魔法-CSDN博客

这里需要注意的是我们软链接的文件(没有就生成)必须与我们的库名一样,因为此刻系统在lib库找个库名;这样我们通过软链接的性质就得到了这个动态库。

2.3安置环境变量:
这里系统还会在它自己的环境变量:LD_LIBRARY_PATH中查找是否有有关动态库的路径;因此我们可以把此路径导入进去即可。

这样就能跑了;为了不干扰后面,我们在unlink掉:

2.4 ldconfig⽅案:
系统一开始还会往这里面的.conf文件里找看是否存在动态库的路径,并沿着路径找动态库 。

因此我们只需要加入一个.conf结尾的配置文件加入动态库的路径即可。

完成添加.conf配置文件并写入路径:

此时程序还是不能跑的,因为我们没有进行刷新配置文件;此刻调用ldconfig刷新一下:

三·一些有关小指令:
ldd +可执行文件 :查看可执行文件的动态链接情况

size +可执行文件:显示目标文件(包括可执行文件)中各个段(section)的大小,以及总的大小。这些段通常包括代码段(text)、数据段(data)、BSS 段(未初始化数据)等。

file+文件:file命令可以用于确定文件类型。它通过检查文件的内容(如文件头、魔数等)来判断文件是何种类型的可执行文件(例如是 ELF 格式的可执行文件、脚本文件还是其他格式)。

四·动静态库同时存在系统行为:
因此大家肯定有个疑问,如果动静态库同时存在且名字相同,那么系统默认会怎么做呢?下面演示一下:

这里报错是无法找到动态链接,故看来系统是默认动态链接了;因此系统优先考虑的是动态库;那么当我们安装程序等的时候系统也会优先对它进行动态库安装以及链接等。

如果我们就是想用动态的话;可以-static 强转一下:

这里就是告诉系统要用静态链接了。

五·目标文件分步编译和链接 :
肯定大家有个疑问,为什么把它们俩分开呢?

假设我们有大量.c文件都编译成了.o文件然后有个.c错了,我们只需要修改其中一个然后再搞成.o与其他大量.o文件进行链接就好;但是如果这两个过程在一起就麻烦了。

六·简单实现库的打包安装及使用:
下面我们以静态库为例演示压下(动态库只需要稍微变动一下即可):

Makefile文件:

libmy.a:print.o print2.o
@ar -rc @^
%.o:%.c
@gcc -c $<
.PHONY:output
output:
@mkdir -p ku/head
@mkdir -p ku/lib
@cp -f .a ku/lib
@cp -f
.h ku/head
@tar -czf lib.tgz ku
@rm -rf ku
@rm -rf .a
.PHONY:clean
clean:
@rm -rf
.a *.o lib.tgz d/ku p

此时的我们:

下面我们来把静态库生成并且解压运行一下:

形成静态库:

打包成压缩包:

把它解压到d目录内:

静态库链接并执行:

清理工作:

本期分享结束了,但是动静态库系列并没有,下面我们就期待博主更新动静态库第二讲吧;欢迎大家阅读!!!

相关文章
解锁动静态库的神秘力量2:从代码片段到高效程序的蜕变(续篇
解锁动静态库的神秘力量2:从代码片段到高效程序的蜕变(续篇
【前端开发者的福音】彻底改变你编码习惯的神奇数组迭代技巧——从基础到进阶,解锁 JavaScript 数组迭代的N种姿势!
【8月更文挑战第23天】在Web前端开发中,数组是JavaScript中最常用的数据结构之一,掌握高效的数组迭代方法至关重要。本文详细介绍了多种数组迭代技巧:从基础的`for`循环到ES6的`for...of`循环,再到高阶方法如`forEach`、`map`、`filter`、`reduce`及`some`/`every`等。这些方法不仅能提高代码的可读性和维护性,还能有效优化程序性能。通过具体的示例代码,帮助开发者更好地理解和运用这些迭代技术。
65 0
震撼!Python元类:解锁编程宇宙的终极秘密武器
【7月更文挑战第4天】Python的元类是创建类的类,用于定制类的行为。例如,通过元类`MyMeta`,可在创建类时动态添加属性,如`version`。在ORM中,元类能自动将类属性映射为数据库表字段。另外,元类也能实现设计模式,如单例模式,确保类只有一个实例。元类提供对Python底层机制的控制,增强了代码的灵活性和功能性。
46 0
解锁Python魔法!装饰器:让你的代码翩翩起舞,简化繁琐逻辑,让编程成为一场戏剧性的华丽变身!
【8月更文挑战第21天】在Python编程中,当需要为函数添加如日志记录、性能测试等功能时,手动重复编写相同代码既冗长又难维护。装饰器提供了解决方案:它是一种特殊函数,包裹目标函数以添加额外功能,而不改变原函数结构。装饰器增强了代码复用性、解耦及灵活性。例如,可通过装饰器轻松记录函数执行时间。更高级用法包括带参数的装饰器、多层装饰器以及使用类作为装饰器。掌握装饰器能显著提升Python代码的质量和效率。
64 5
Kotlin字符串秘籍:解锁高效处理与创意应用,让你的代码闪耀不凡!
【8月更文挑战第2天】Kotlin是一门现代化的静态类型语言,以简洁、安全及强互操作性著称,在Android及服务器端开发中广受好评。本文通过与其他语言对比,深入解析Kotlin中字符串的基础和高级用法。Kotlin简化了字符串拼接,支持直接使用`+`操作符,并引入了直观的字符串模板。它提供了丰富的字符串操作函数,如使用索引范围进行子字符串提取,增强了代码的可读性。Kotlin字符串的不可变性提升了程序稳定性。利用扩展函数特性,可以轻松定制字符串行为,提高代码的模块化和重用性。掌握这些技巧能显著提升开发效率和代码质量。
79 1
汇编高手秘籍:解锁性能优化新境界,用汇编语言让你的程序飞起来!
【8月更文挑战第31天】汇编语言作为编程基石,其高效性能备受推崇。尽管现代软件开发更偏爱高级语言,但在性能要求极高的场景下,汇编优化仍不可或缺。本文通过示例代码介绍四种优化技巧:循环展开、寄存器分配、指令重排及SIMD指令使用,显著提升执行效率。同时强调分析性能瓶颈、测试优化效果及保持代码可读性的重要性,助力开发者在关键代码路径上实现性能突破。
310 0
揭秘!Bottle框架如何以极简之力,解锁高效Web开发新纪元?一行代码,改变你的开发世界!
【8月更文挑战第31天】当你踏入Web开发领域,是否渴望找到一款既高效又简洁的框架?Bottle正是这样一款用Python编写的轻量级WSGI框架,以其紧凑的核心代码、简洁的API和易上手特性脱颖而出,非常适合小型项目和快速原型开发。它通过直观的路由系统、内置HTTP请求/响应封装及多种模板引擎支持高效开发。
68 0
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
101 0
解锁Django模板系统终极奥义!揭秘高效前端渲染秘籍,让你的网站秒变炫酷黑科技!
【8月更文挑战第31天】Django作为Python的高级Web框架,内置的模板系统支持动态HTML渲染。本文通过在线书店案例,详细介绍Django模板系统的设置与高效渲染技巧,包括创建模板文件、编写视图函数及URL配置。通过合理使用过滤器、深度查询和模板继承等技巧,提升前端渲染效率和安全性,优化Web应用开发流程。
64 0
TypeScript:解锁JavaScript的超级英雄模式!类型系统如何化身守护神,拯救你的代码免于崩溃与混乱,戏剧性变革开发体验!
【8月更文挑战第22天】TypeScript作为JavaScript的超集,引入了强大的类型系统,提升了编程的安全性和效率。本文通过案例展示TypeScript如何增强JavaScript:1) 显式类型声明确保函数参数与返回值的准确性;2) 接口和类加强类型检查,保证对象结构符合预期;3) 泛型编程提高代码复用性和灵活性。这些特性共同推动了前端开发的标准化和规模化。
87 0