肃北蒙古族自治县建设局网站,怎么做好网站开发 设计,抖音广告投放平台官网,什么是响应式设计什么是库
库是写好的现有的#xff0c;成熟的#xff0c;可以复⽤的代码。比如#xff0c;在平时编写代码时#xff0c;许多函数都是通用的#xff0c;如果没有库#xff0c;人们在编写代码时就需要将这些通用的函数都自己实现一份。将这些通用的函数都编写到一起#…什么是库
库是写好的现有的成熟的可以复⽤的代码。比如在平时编写代码时许多函数都是通用的如果没有库人们在编写代码时就需要将这些通用的函数都自己实现一份。将这些通用的函数都编写到一起这样就形成了一个库。
在Linux下 静态库xxx.a 动态库xxx.so
在windows下 静态库xxx.lib 动态库xxx.dll
库的制作
动静态库中要不要包含main函数
如果自己写的库不想被别人链接可以写一个main函数
静态库 所有的库无论是动的还是静的本质都是源文件对应的.o 静态库的本质就是.o文件打了一个包或者说本质是一种归档文件归档后只需要使用gcc/g直接进行链接即可.
ar表示将文件进行归档归档后的文件叫libmyc.a即一个静态库这个静态库的库名叫“myc”。-rc表示如果将.o文件进行打包时有新增的文件则直接打包进去即可c如果.o文件的内容更新了直接将更新后的.o文件对包中的对应源文件进行替换即可(r)。简单讲就是需要替换的就替换有需要一起打包的新源文件就直接一起打包 讲.o文件与库文件进行链接
-L.表示在当前路径下查找库文件-lmyc表示要链接的库叫myc 如果要链接任何非c/c标准库都需要指明-L -l意思是要指明在哪里查找库要链接的库叫什么
为了方便对库文件进行管理可以将需要用到的库文件管理在“lib”目录下 在目标文件链接库文件时 链接完后就形成了可执行程序 库也是被安装到系统中的。linux下库在/usr/lib64路径下头文件在/usr/include路径下 对于库的安装就是将库的头文件与库文件拷贝到系统指定目录下在链接时只需要“-l库名”就可以了。
动态库
制作动态库与静态库类似也是将文件打包成库。
-fPIC产⽣位置⽆关码(positionindependentcode)
-shared表示形成的是动态库 形成静态库需要使用到ar指令因为静态库是一个归档文件而动态库不是
对库进行链接会发现能生成指定的可执行程序但是依然会报找不到库的错误 检查可执行程序链接的库发现真的是无法找到库 为什么会这样
因为可执行程序所依赖的动态库是需要被系统知道的在创建可执行程序时只是告诉了gcc动态库的位置。系统≠gcc
静态库为什么没有这个问题
因为静态库在链接时是直接将库的实现拷贝到可执行程序里
怎么解决
因为系统是去指定的路径下找库所以第一种方法
将自己写的动态库拷贝到系统指定路径下即可 第二种方法
软链接 第三种方法
OS除了在指定路径下查找动态库也会在该环境变量下查找LDLIBRARYPATH
该环境变量通常是空的 将动态库的路径导入到这个环境变量中 一旦关闭了shell导入的这个环境变量就没了 第四种方法
更改系统的配置文件
这个路径下用于存放 动态链接器ld.so 的额外配置文件这些文件告诉系统在哪些目录中搜索共享库.so 文件。 创建一个我们自己的conf配置文件并将动态库路径写进去 使用这个指令重新加载配置文件 四种方法总结
将动态库拷贝到系统指定路径下 使用软链接将动态库路径写入LDLIBRARYPATH路径中去 向/etc/ld.so.conf/路径下添加配置文件
当动静态库同时存在时可执行程序会链接哪个库呢
动态库 链接任何库之前库都必须存在。像上面动静态库都存在想链接静态库就需要使用-static 但前提条件是静态库必须存在
gcc/g默认使用动态库 在Linux系统下默认情况安装的大部分库默认都是优先安装动态库 库应用程序 1N vs不仅仅形成可执行程序也能形成静态库
目标文件
形成可执行程序的过程预处理、编译、汇编、链接。但其实归根揭底就两步编译、链接 形成的.o文件全称叫做可重定向目标文件
进行链接其实就是将所有.o进行链接。
为什么要先编译成.o文件 在一个大项目中有许多的.c文件如果不先编译成.o文件而是直接将.c文件经过编译器输出成可执行程序那么当程序中某个.c文件出现问题时就需要将出错的.c文件修改再将所有文件进行重新编译。 有了.o文件就只需要将出错的.c文件重新编译就可以了
ELF⽂件
我们知道可执行程序是有自己固定的格式的会分为多个模块的比如数据段代码段…
动静态库、可执行程序、.o文件也是如此它们是以一定的格式将内容放入到二进制文件中的也就是ELF格式 我们自己的可执行程序是有上图这般的格式的
最常见的部分 代码节.text⽤于保存机器指令是程序的主要执⾏部分。 数据节.data保存已初始化的全局变量和局部静态变量。
文件被编译后代码则在代码节中数据则在数据节中。数据节与代码节分别会占用数个section
size计算得出的是程序中几个数据节的大小
ELF从形成到加载轮廓
ELF形成可执⾏ step-1将多份 C/C 源代码翻译成为⽬标 .o文件动静态库 step-2将多份 .o ⽂件section进⾏合并 将多个.o文件、动静态库的对应的section部分的节进行合并形成大的可执行 ELF可执⾏⽂件加载 ⼀个ELF会有多种不同的Section在加载到内存的时候也会进⾏Section合并形成segment段。 合并原则相同属性⽐如可读可写可执⾏需要加载时申请空间等.比如字符串常量区代码区就会进行合并) 很显然这个合并⼯作也已经在形成ELF的时候合并⽅式已经确定了具体合并原则被记录在了 ELF的 程序头表 (Program header table) 中
Section Headers是一个数组。可以把他理解为一个线性数组当我们要拿其中的某一个section时就是从这个线性的数组中取出数据。 ELF格式中有一个data节与bss节。 data中保存的已初始化的全局变量和静态变量 的 值。 在bss中保存的是未初始化的全局变量和静态变量其核心特点是 在文件中不占用实际存储空间仅在程序加载到内存时分配并初始化为零。 比如当我们有一个程序中有50个int类型的全局变量但没有初始化那么这50个全局变量不需要保存在data节中只需要在bss节中用一个int[50]来记录没有初始化的全局变量的初始值为0当我们加载这个程序的时候再将Int[50]展开分配空间并初始化为0 查看ELF Header
eadelf -h 要查看的程序 每个ELF区域与文件的偏移量之间存在联系
理解连接与加载
静态库是如何形成可执行程序的
静态链接 ⽆论是⾃⼰的.o,还是静态库中的.o本质都是把.o⽂件进⾏连接的过程 所以研究静态链接本质就是研究.o是如何链接的
对.o文件进行反汇编我们看到callq的地址是00 00 00 00这是因为编译器编译.c文件时不知道调用函数的地址是多少所以先暂时设为0 尽管调用了一个没有声明没有函数体的函数的函数但是编译依然没有报错。这就证明了编译器在编译.c文件时是不认识调用的函数的不知道函数的真实地址是多少。 那这个地址会在什么时候进行填充修正呢?
链接的时候
printf底层实际上调用的就是puts函数 观察hello.o的符号表 当将这些.o文件进行链接时实际上就是将文件中的这些未定义的模块去其他模块中找 当链接后callq 00 00 00 00的地址全都填充为具体的值了 最终 两个 .o 的代码段合并到了⼀起并进⾏了统⼀的编址 。链接的时候会修改 .o 中没有确定的函数地址在合并完成之后进⾏相关 call 地址完成代码调 ⽤
静态链接就是把库中的.o进⾏合并和上述过程⼀样
所以链接其实就是将编译之后的所有⽬标⽂件连同⽤到的⼀些静态库运⾏时库组合拼装成⼀个独⽴ 的可执⾏⽂件。其中就包括我们之前提到的地址修正当所有模块组合在⼀起之后链接器会根据我 们的.o⽂件或者静态库中的重定位表找到那些需要被重定位的函数全局变量从⽽修正它们的地址。这 其实就是静态链接的过程。
所以链接过程中会涉及到对.o中外部符号进⾏地址重定位
ELF程序如何加载到内存的ELF如何转换成进程的逻辑地址物理地址虚拟地址空间
一个可执行程序如果没有被加载到内存中该可执行程序有没有地址?
有地址
当要查找某个模块时只需要根据起始地址和偏移量就能查找到。
磁盘上的地址叫做“逻辑地址”。
后面优化成每个程序只要一个segment且起始地址为0每个模块的偏移量都是根据这个一个segment来说的 当代计算机编址平坦模式编址
这些地址也叫做线性地址
这前讲到线性地址的地方是关于程序的虚拟地址空间部分。
这里关于对磁盘上的可执行程序进行编址其实就是虚拟地址的统一编址
当文件被编译好之后函数之间互相调用的地址就是虚拟地址了