0


Linux 详细了解动静态库创建以及内部详细,全方位讲述,要想知道什么是动静态库,看这一篇就够了

大家好呀,我是残念,希望在你看完之后,能对你有所帮助,有什么不足请指正!共同学习交流哦!
本文由:残念ing原创CSDN首发,如需要转载请通知
个人主页:残念ing-CSDN博客,欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:[残念ing 的【Linux】系列专栏——CSDN博客]
在这里插入图片描述

1. 创建静态库

创建.c .h 文件
编译成 .o 文件 gcc -c
建立静态库 ar -rc libmystdio.a xxxx.o xxxxx.o …

方法1:将静态库交给系统并下载使用
sudo cp *.h /usr/include/
sudo cp libmystdio.a /lib64/
在编译可执行文件时,要注意,之前的编译方法对于我们自己弄的第三方库,要

gcc main.c -lmystdio

这样进行编译,mystdio是libmystdio.a去了头去了尾的

方法2:
cp *.a …/xxx
cp *.h …/xxx
在编译可执行文件时,如果库和源文件在一起,gcc在查找静态库的时候,不会在当前目录查找,那就要用

gcc main.c -o main -L. -lmystdio

告诉编译器,编译的时候,查找库,除了系统路径,也要在我指明的路径下找

方法3:
打包压缩

 tar -czf stdc.tgz stdc

//使用 tar 工具将 stdc 目录打包并压缩为一个 .tgz 格式的归档文件
cp 到要使用的目录下
解压

tar xzf stdc.tgz

(解压的文件名)
在编译可执行文件时,如果使用的是带路径的库,编译时就要用

gcc mian.c -I stdc/include -L stdc/lib -lmystdio

在指定目录下查找库。
gcc mian.c -I stdc/include //解决头文件问题
gcc mian.c -I stdc/include -L stdc/lib -lmystdio

实现Makefile

libmystdio.a :mystdio.o
  2   ar -rc $@ $^3   @echo "ar -rc ...... done"4%.o:%.c
  5   gcc -c $<6   @echo "gcc -c ...... done"7.PHONY:clean
  8 clean:9   rm -f *.a *.o stdc
 10   @echo "clean ...... done"11.PHONY:output
 12   @mkdir -p stdc/include
 13   @mkdir -p stdc/lib
 14   @cp -f *.h stdc/include                                                                                                               
 15   @cp -f *.a stdc/lib
 16   @tar -czf stdc.tgz stdc //将stdc打包压缩17   @echo "output stdc ..... done"

2. 动态库的创建

将 .c ----> .o gcc -fPIC -c my_stdio.c
打包 gcc -o xxxxx.so my_xxxx.o my_xxxx.o -shared //shared告诉编译器不要产生可执行文件

使用方法1
sudo cp *.h /usr/include/
cp xxxx.so /lib64
在编译可执行文件时,要注意,之前的编译方法对于我们自己弄的第三方库,要 gcc main.c -lmystdio 这样进行编译,mystdio是libmystdio.a去了头去了尾的

补充
1 可以查看 可执行文件,依赖的是哪些库 ldd a.out(可执行文件名)
2 当我们删除了动态库后,可执行文件就不可以执行了,但是当我们删了静态库后可执行文件照样可以执行

使用方法2
当 .c .h 动态库在同一级目录下时
在编译可执行文件时,gcc在查找动态库的时候,不会在当前目录查找,那就要用 gcc main.c -o main -L. -lmystdio 告诉编译器,编译的时候,查找库,除了系统路径,也要在我指明的路径下找

使用方法3
当这级目录下,只存在 主函数(mian .c )
打包压缩:tar -czf stdc.tgz stdc //使用 tar 工具将 stdc 目录打包并压缩为一个 .tgz 格式的归档文件
cp 到要使用的目录下
解压 tar xzf stdc.tgz(解压的文件名)
在编译可执行文件时,如果使用的是带路径的库,编译时就要用 gcc mian.c -I stdc/include -L stdc/lib -lmystdio 在指定目录下查找库。
gcc mian.c -I stdc/include //解决头文件问题
gcc mian.c -I stdc/include -L stdc/lib -lmystdio

注意这里会出现一个问题,也就是可执行文件,不能运行,通过ldd 检查会发现,这个可执行文件无法找到依赖的动态库

解决的办法
1 将动态库交给系统的默认目路径下 比如 /lib64
2 为该动态库在系统路径 建立软链接

sudo ln -s 动态库路径/动态库名 系统路径

在这里插入图片描述
在这里插入图片描述
3 将对应的当前所在的库路径,添加到环境变量 LD_LIBRARY_PATH 中,

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH :绝对路径
echo $LD_LIBRARY_PATH 

4 将库所在路径配置到 /etc/id.so.conf.d/ 里面,并且在配置完后,ldconfig 更新一下文件。

sudo vim /etc/ld.so.conf.d/xxxx.conf

打开后将库路径放入,(注意:当普通用户不可以时,建议直接使用超级用户)

补充:如果同时为程序提供动态库和静态库,那么gcc/g++ 默认使用动态库,如果你就是要静态链接(前提是必须提供对应的静态库),那么再最后加static就可以了。如果只有静态库,但是连接的方式是动态链接,那么gcc、g++ 就只能针对你的.a 文件局部采用静态链接了。

3. 可执行程序格式(ELF)

链接:就是我们的一个一个的相同属性的section进行合并
在这里插入图片描述

readelf -h main

将一个可执行文件的ELF的头部信息读出来
对任何一个文件,文件的内容就是一个巨大的“一维数组”,要标识文件然后一个区域,用的方法就是:偏移量+大小 的方式
在这里插入图片描述

4. 重新理解地址空间(mm_struct)

4.1 可执行程序有没有地址的存在?(有的)

在这里插入图片描述
总结:虚拟地址空间是由操作系统、cpu、编译器共同协作下的产物。

在这里插入图片描述

ELF在没有加载到内存的时候,就已经按照[0000,FFFF](虚拟地址)进行编址了,这也说明:编译器在编译时,就已经形成虚拟地址了。
在磁盘ELF上的逻辑地址==加载到内存中的虚拟地址

在这里插入图片描述

4.2 mm_struct 由谁来初始化

在这里插入图片描述
在这里插入图片描述

总结:mm_struct 下会有一个struct vm_area_struct 这样的结构体,里面的结构跟链表差不多,每个结点会根据每个指令的大小和偏移量,来记录起始地址。

5. 动态库是怎么加载的?

看一图就可以理解
在这里插入图片描述
库方法地址:本质就是库中的偏移量(lib.so:偏移量)
动态库被加载到内存中后也是要被OS管理的(先描述,再组织)
GOP+库方法偏移量=下一个库方法(与地址无关)

标签: linux restful 运维

本文转载自: https://blog.csdn.net/m0_73523775/article/details/144171711
版权归原作者 残念ing 所有, 如有侵权,请联系我们删除。

“Linux 详细了解动静态库创建以及内部详细,全方位讲述,要想知道什么是动静态库,看这一篇就够了”的评论:

还没有评论