基础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月前
|
搜索推荐 索引
【文件IO】实现:查找文件并删除、文件复制、递归遍历目录查找文件
【文件IO】实现:查找文件并删除、文件复制、递归遍历目录查找文件
34 2
|
1月前
|
编解码 Java 程序员
【文件IO】文件内容操作
【文件IO】文件内容操作
42 2
|
1月前
|
存储 Java API
【文件IO】文件系统操作
【文件IO】文件系统操作
40 1
|
2月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
1月前
|
存储 Java 程序员
【Java】文件IO
【Java】文件IO
35 0
|
2月前
|
Linux C语言
C语言 文件IO (系统调用)
本文介绍了Linux系统调用中的文件I/O操作,包括文件描述符、`open`、`read`、`write`、`lseek`、`close`、`dup`、`dup2`等函数,以及如何获取文件属性信息(`stat`)、用户信息(`getpwuid`)和组信息(`getgrgid`)。此外还介绍了目录操作函数如`opendir`、`readdir`、`rewinddir`和`closedir`,并提供了相关示例代码。系统调用直接与内核交互,没有缓冲机制,效率相对较低,但实时性更高。
|
3月前
|
存储 监控 Linux
性能分析之从 IO 高定位到具体文件
【8月更文挑战第21天】性能分析之从 IO 高定位到具体文件
40 0
性能分析之从 IO 高定位到具体文件
|
3月前
IO流拷贝文件的几种方式
IO流拷贝文件的几种方式
36 1
|
4月前
|
Linux 数据处理 C语言
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
73 0
|
5月前
|
C++
Open3D File Io 文件IO
Open3D File Io 文件IO