基础IO+文件(三)

简介: 基础IO+文件

动静态库


动态库和静态库


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

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

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

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

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

先完成一个小任务,在一个目录中完成两个函数的实现,然后将其二进制可执行文件.o还有头文件.h拷贝到另一个目录中,使用它自己的main函数来完成最后的链接执行这个两个函数


加减函数的实现和头文件如下


ebfbed2a3a9c15aea85a2c06e6fa553c_86b64cb36a0f43349ac5b75345616bbf.png


782c8bbbf6da621d41ea91dde705f9c7_c2dccd78f5c54fff96973b85d931ba60.png

通过 gcc -c生成可执行二进制文件

e313afdaba14fd2e5bc449387b006860_01a6ad41477342fbaf2be2d11468cafd.png


将所有 .o文件和头文件.h拷贝到另一个目录中


179584a48933c6ea1c55fa0a8e877751_9fd353181f854d398884060966bba7ee.png


main.c


0266950035862c3bdde1774599b6a43f_946f2de86e1f45ba9ce75659f202d2e7.png


链接最后运行程序

1b71d15185ab4e6c3013b4b91dc635a9_9b834bae6734413d8e5a25555d032b30.png


所以如果我们不想给对方自己的源代码,只需要提供对方 .o方法的实现, .h包含的方法,对方便可使用自己的代码进行链接最后执行


如果有很多方法,那就需要拷贝多份 .o文件,是不是很麻烦呢???所以想了个办法,将所有的 .o文件进行打包,只提供对方一个文件,而这个文件也称为库,库又分为静态库和动态库,接下来就来学习吧


生成静态库


先介绍两个指令

ar:是归档指令, archive将文件打包到一个文件中


rc:表示 replace and create


1539332c4ed6238671bba3fa82686b31_d38601abf3dd4c95ba26b0a1f7adc904.png


这只是将库文件进行了打包,在上面的例子中,还包括了头文件,所以还需要进行改进

output:称作发布版本,打包之后便可进行发布


9968aae9161f5c345e05d621fbc1f0f8_1ccfe026bfe84b398bfd337e82bff274.png

ea0c407153d0ac0dd6e7fffd63385562_90739fc20c874b61a85378a734faf3bf.png

96e80e31b4ba7729271815ce491c4181_ca0e0f0b80ba4cf88c80d9b6f131e2d9.png


自己生成的静态库便完成了,只需要进行发布即可


将库进行压缩,发布

16e7315e22bb93b76f723e164e4aab4a_ed6e62b9d3b4400c83994ef9d257312f.png


在测试目录中进行库的下载(也就是拷贝),解压


c742e9d4b43f6d2dc07b2f3ef87c351a_431ba0dd47a6483a8dacbac6783d2efe.png


在进行链接时,Linux有些不同,在之前的学习中,链接阶段都是现在当前程序中寻找头文件,然后再到其他程序中寻找头文件;还需要告知编译器,当前库所在路径,不经如此还要告知其库的名称,当然在之前的学习中这一切都是编译器默认所做到


所以,链接操作如下

-I ./mylib/include:告知编译器所包含的头文件

-L ./mylib/lib:指明库所在路径

-l math:指明库名称


1553a292481597ffa0d089f47490c2ad_409480b5713e4a99a7aecd3ae3902671.png


还剩最后一个小问题,观察下列指令

be49dfdcecefbb59e71c7d762f961a27_518613ca2082456497fbf742451465cf.png


为什么 mymath是动态链接的,并且编译器所罗列的库中并没有刚刚自己所写的库,这是为什么呢???


gcc默认是动态链接的,如果只有一个库,最后是动态链接还是静态链接却决于这个库的类型;但是如果存在很多库,当链接时如果使用了一个动态库,则就是动态链接,上面在最后链接时,库只提供了静态库,而默认是动态链接,所以只能将将代码拷贝到可执行程序中使用动态库进行链接


生成动态库


与静态库类似,有一点区别

在生成.o文件时,需要加上fPIC生成位置无关码

6ed4c2982387ecec3b91daa92cc9ec5c_2c35e9eb08644c918ada4e8c0ccc6402.png


进行文件打包,这里可以直接使用gcc再加上shared生成共享库格式即可


6748283e8afd1bccf20f9ffcae0301ce_74ca36ab3eff4050b442e15adbd8073a.png


分别将头文件和库文件放入相应的目录中,拷贝给测试目录

61ebb2071927f98153b7d26d85f12ea0_02eaef5b01a149e29c0625fe881e1bde.png


最后进行链接执行程序

b2d13304402f829a9bceba337880617f_9b812e7918c84b4ca1955b06b84d1bb3.png

545cbdd08ffb9bbfb46c016640131452_ac068f1e3c484e16ae7ffab6a0ba6671.png


这里与静态库有所不同,动态库已经加载到程序中,但是并没有找到;在链接时,我们已经将库文件,路径和库名称都告知了gcc,当程序链接之后,与编译器就无关了;运行时操作系统和命令行解释器也是需要知道库所在的位置,但是由于库并没有在系统的默认路径下,所以操作系统无法找到,程序也就无法进行


解决措施也很简单,只需要将库路径添加到默认搜索路径即可,在当前目录中进行软链接,程序即可运行


725e6ac2bad71b04306b76864d3d163c_3873fc8feffd4b05817a4c6043d577e2.png


动静态库的加载


静态库


静态区并不是加载到内存中的,在程序运行时所需要使用的函数被拷贝到程序的代码段中,且必须按照相对确定的地址进行编址,称作绝对编址;再由程序拷贝到内存中,再通过虚拟地址空间映射到代码段上进行访问

图解如下


ac681f1bb6a24268aba0f4ed3d0d8718_ee8d32bc3d244fa5ad2a5bdebb7d932a.png


动态库


2f6b44a1e56b199193ee47144383a6b6_7222eabf72e4462ca0f1980598da579d.png


动态库的加载是相对位置的加载,在程序中存在着库中函数的偏移量,这也解释了为什么上面使用 fPIC生成位置无关码;程序加载到内存中的代码段,通过页表映射到虚拟地址空间的代码段中,当程序执行到库函数时,此时程序中只有函数的偏移量,进程便停止,将动态库加载到内存中,再通过页表映射到虚拟地址空间中的共享区,一旦库函数加载到共享区中,起始位置就确定了,然后程序通过偏移量在库中寻找对应的函数,至此动态库加载的内容结束


目录
相关文章
|
1月前
|
Java Unix Windows
|
11天前
|
C++
Open3D File Io 文件IO
Open3D File Io 文件IO
|
19天前
|
存储 缓存 Unix
【嵌入式软件工程师面经】Linux文件IO
【嵌入式软件工程师面经】Linux文件IO
21 1
|
22天前
|
存储 安全 Unix
【.Net Core】深入理解IO之文件和目录
【.Net Core】深入理解IO之文件和目录
30 4
|
22天前
|
Java
io读两个文件,生成list 排重后写本地文件(Java)
io读两个文件,生成list 排重后写本地文件(Java)
13 2
|
2天前
使用字节输入流报错 java.io.FileNotFoundException: srcdruid.properties (系统找不到指定的文件。)
使用字节输入流报错 java.io.FileNotFoundException: srcdruid.properties (系统找不到指定的文件。)
6 0
|
28天前
|
Java
|
29天前
|
Java API
文件IO (File对象, 文件读写)
文件IO (File对象, 文件读写)
26 2
|
1月前
|
消息中间件 关系型数据库 Kafka
实时计算 Flink版操作报错之在执行任务时遇到了一个IO错误,具体表现为无法从本地主机(localhost)下载文件,该怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
1月前
|
C++ 数据格式
【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]
【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]
【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]