您的位置:首页 > 房产 > 建筑 > 信息流推广渠道有哪些_上海企业服务云平台_选择一个产品做营销方案_360网站推广

信息流推广渠道有哪些_上海企业服务云平台_选择一个产品做营销方案_360网站推广

2025/4/19 6:02:10 来源:https://blog.csdn.net/m0_74207969/article/details/144883151  浏览:    关键词:信息流推广渠道有哪些_上海企业服务云平台_选择一个产品做营销方案_360网站推广
信息流推广渠道有哪些_上海企业服务云平台_选择一个产品做营销方案_360网站推广

目录

1.库

库的概念

ar指令

如何使用库文件

如何安装库

直接安装到系统路径下

软连接的方式

环境变量

2.动静态库

静态库与动态库的区别

如何使用

Makefile自动化创建动态库

3.动态库的加载

加载逻辑

绝对偏移和相对偏移


1.库

库的概念

        对于C/C++来说,一个可执行文件的形成是经过多个源文件编译形成.o文件,多个.o文件链接形成可执行文件的。那么如果把很多除了带main函数的源文件编译形成.o文件,同时提供这些.h文件,用户把自己写的文件中引入这些.h头文件,把自己的文件编译形成.o文件后,和其他.o文件一同链接形成可执行程序。这里使用者引入的其他.o文件就是打包好的库文件。

         因为一个可执行程序只能有一个main函数入口,所以说库文件中是不可以带main函数的。

ar指令

ar-rc  库名称   一个或多个.o文件

        ar工具可以将多个.o文件打包形成库文件,rc则是库文件代表存在则替换,不存在则生成库 。

如何使用库文件

        首先就是需要在我们的代码中包含库配套提供的头文件,在编译的时候就可以直到该将库中的哪些文件引入进来了。但是如何找到库文件呢?

gcc TestMain.cc  -I(大写i)头文件路径     -l(小写L)库名称     -L库路径 

        这样的话就可以使用了,那我们平时写代码的时候为什么不需要带这些库名称和库路径呢?因为我们安装的C/C++开发环境会自动将头文件和库文件放到指定的搜索路径下,我们平时安装库也是一样的放在了(usr/include 和 lib64)目录下。系统会自动查找该路径下的头文件和库文件,如果我们的库安装到该路径下的话,也是可以不用在编译的时候带-L参数的。(库名称在使用时要去掉lib和后缀)

        但是安装到指定路径下之后,是可以找到头文件和库文件,但是程序怎么直到用哪一个库呢?所以我们还是要带上-l参数指定要使用哪一个库,为什么gcc/g++不需要呢?因为gcc默认编译的就是C程序、g++默认编译的就是C++程序所以他们默认直到要使用什么库,所以不需要再指定的说明要使用哪一个库了。

        也就是说将头文件和库文件放到指定的搜索路径下可以解决路径问题,但解决不了具体使用哪个第三方库的问题,还是要自己指定库名称。

如何安装库
直接安装到系统路径下

sudo cp 头文件路径   /usr/include/

sudo cp 库文件路径   /lib64/

软连接的方式

        第一种是在当前路径下建立与特定位置头文件与库文件的软连接,因为每个进程都有自己的当前工作目录,会现在当前工作目录下寻找,找不到后才会在环境变量记录的特定位置中寻找,所以在进程的工作目录下建立软连接也是可以的,这样就不需要安装到系统路径下了。

        第二种的话则是将软连接安装到系统中,在/usr/include和/lib64/路径下建立头文件和库文件的软连接,注意链接名要和库文件名一样。这样的话系统在扫描特定路径下时,就会通过软连接扫描到对应的位置。

环境变量

        修改LD_LIBRARY_PATH环境变量,将库文件的路径添加到其中,也可以实现不用指定路径,编译器会在该环境变量提供的路径中寻找。注意编译器不是所有的环境变量都会查找,会收到配置文件的限制,所以我们随意设定的一个环境变量是不可以的。

2.动静态库

静态库与动态库的区别

        静态库是以lib开头以.a结尾,动态库则是以lib开头以.so结尾。

        两者都是将源文件编译形成.o文件,然后将.o目标二进制文件打包后,形成了库文件。但是两者在形成可执行程序的时候有很大的区别,对于静态库来说,编译器和链接器在链接阶段会将静态库的代码整合到可执行程序中,形成只会就不再需要静态库了。而动态库的话,不会这样,而是在运行时,系统一边运行程序,一边加载动态库到内存中。

如何使用

        一般编译器默认的话都会以动态库的方式进行连接库文件,如果我们想要使用静态库的方式连接库文件的话,就需要在gcc/g++编译选项后面带上 -static参数,这样的话所有依赖的库文件都会以静态库的形式参与编译和连接。一般大型的项目程序的话都会提供动态库和静态库两种文件,因为各自有各自的优势,所以上述不带-static就会默认使用动态库文件了。当然不指定static也可以使用静态库文件。

        对于动态库来说,如果不适用上述说的方法将库文件放入到系统指定的搜索路径下的话,不仅仅在编译的时候需要告诉编译器去哪里找库文件,同时在执行程序的时候,是动态加载的,所以还要告诉可执行程序去哪里寻找动态库。而且运行的时候-l、-L是无效的,他们属于编译时候的选项,所以最好还是配置到系统路径下。

Makefile自动化创建动态库
#编译动态库
dy-lib=libmylib.so
$(dy-lib):test1.o test2.ogcc -shared -o $@ $^
%.o:%.cgcc -fPIC -c $<#发布动态库
.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp -f *.h mylib/includecp -f *.so mylib/lib
.PHONY:clean
clean:rm -rf *.o *.so mylib

3.动态库的加载

加载逻辑

        一个程序的变量名、函数名等各个内容在编译的时候都会转化为二进制序列,编译的时候对代码进行编址,也会遵循虚拟空间的那一套逻辑,这样加载到内存的时候,也可以更好的进行页表的映射。也就是说程序在没有加载到内存之前就已经编好了逻辑地址,也就是基地址+偏移量。所以说程序在被编译好形成可执行程序之后,在磁盘中存储的方式也就定义了运行的逻辑了。

        动态库也是磁盘的文件,所以在访问的时候,也需要先被加载到内存中,进行虚拟地址和物理地址的映射才可以,而动态库的文件是映射在栈区与堆区之间的共享区内。因为该区域收到栈区和堆区的影响所以说加载的位置也是不确定的。

        操作系统在把可执行程序映射完毕之后,会读取程序的符号表信息,如果说查询到涉及到动态库的内容时,加载器才会将对应的动态库文件加载到内存映射到虚拟空间中的共享区内部。在加载之前,动态库中的每个.o程序都会有一个符号表,只会把相对偏移量填入符号表虽然说加载的位置不一定,但是映射到虚拟内存之后的位置是固定的不变的,那么动态库在库在虚拟内存中就有了固定的起始地址了,就可以把符号表中库函数对应的空白地址替换成库起始地址 + 偏移量了。

        我们对于访问动态库中的内容,说到底也是要代码区访问,所以说涉及到库文件的内容的时候,需要访问的指针在虚拟空间的正文区和共享区之间来回跳转的。

        多进程下,如果是很多个进程都用到同一个动态库的话,应该也是只会加载一份动态库数据到内存中的,所以操作系统应该把加载到物理内存的动态库维护起来,如果多个进程同时使用一个动态库的话,操作系统会知道,然后把多个进程的页表映射到该动态库位置即可。        

绝对偏移和相对偏移

        偏移量分为绝对偏移和相对偏移,绝对偏移的话,偏移量是相对于整个空间的,而相对偏移是对于一部分空间的起始位置来计算的。 对于动态库来说,因为其加载位置不一定,所以起始地址就不一定,所以不能使用绝对偏移,而使用相对偏移,不管起始位置在怎么变化,偏移量都是相对于起始位置的,所以说不会因为起始地址的改变而发生影响。所以动态库在加载的时候采用的是相对偏移编址的方法,所以gcc在编译的时候要加上 -fPIC与位置无关码选项,这样的话就会采用相对偏移编址,同时采用一些其他策略,就可以实现代码加载到任何位置都可以正确执行。

        那为什么普通的代码数据不需要这样编译呢?前面也提到了一个可执行程序在被编译的时候,也是遵循的虚拟地址空间那一套逻辑的,在磁盘中存放的数据格式与位置和在加载到内存只会的格式和位置一样,所以就相当于是在编译形成可执行程序后,加载到虚拟内存的位置就也固定了,所以使用绝对编址或相对编址也没有太大影响。动态库就并非如此了。

       

       

        

        

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com