当前位置: 首页 > news >正文

软硬链接与动静态库的加载

软/硬链接

软链接

ln -s 

在这里插入图片描述软连接是一个独立的文件,其内容是目标文件的路径。
也就是类似windows的快捷方式

硬链接

在这里插入图片描述

引用计数变为2(也就是硬链接数),是同一个文件

作用

用软连接来快速访问(硬链接用的少一些)

///软硬链接和静态库后面会再写一篇

动态库

gcc -c -fPIC name.c
#生成静态库那里是
# gcc -o name.c

生成name.o文件

fPIC:产生位置无关码(后面再讲)

动态库打包只需要使用gcc

gcc -shared -o libname.so name.o name1.o
# -o 紧跟后面的.so

shared 生成共享库格式

补充:makefile语法
$^:表示依赖当前目录下所有文件
$<:表示将一个一个的取出文件,并执行相应的命令

%.o:%.cgcc -c -fPIC $<
# 写了.o的情况下  可以不再写-o

比如当前目录下有是个.c文件 那gcc命令就会执行十次

%.o:表示所有后缀为.o的文件

尝试编译:链接谁?在那里?

因为我们写的库是第三方库 所以编译文件的时候 需要说明你链接的是哪个库

gcc name.c -lmyname
#-l 表示链接
#去掉前面的lib  去掉后面的.so

并且由于gcc一般是在默认路径下去搜索库的

你写的库在当前路径下 gcc找不到

所以我们就需要说明库在哪:-L

gcc name.c -L. -lmyname

也可以把我们创建的库 放到默认路径
比如/lib64

补充: ldd file
查看这个个文件会链接到哪个库

利用库来进行编译

我们先将所有头文件(include文件夹)和静态库(lib文件夹)打包进一个压缩包(mylib)内
然后创建user文件夹(假设是用户)
进入user目录 复制(下载)压缩包并解压
这就模拟了我们在网站上下载库的过程

#现在user目录下有两个
main.c
libgcc -o mytest main.c
#编译main.c

报错了 找不到lib里的头文件

我们就需要用 -I ./mylib/include 来表示我们编译需要的头文件在哪

仍然链接报错了

这回是链接错误 和上一小节一样 你没有指明库在那里

-L ./mylib/lib -lmyname

好麻烦 我想少写一些

那么我们就可以把这些拷贝到默认路径下
这就是安装!

而这些默认路径的创建一般是root创建
这就是为什么下载 移动 复制 都需要sudo

拷贝完就可以简写成

gcc -o mytest main.c -lmyname

运行

又错辣!
显示找不到libmyname.so这个文件 静态库就没这个问题(因为静态库编译完就没事了

我们前面虽然告诉了编译器 库在那里,但操作系统在执行可执行程序(mytest)的时候 并不知道

四种方法

  1. sudo cp mylib/lib/* /lib64
    把写的拷贝到默认路径

  2. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xx/xx/xx/mylib/lib
    LD_LIBRARY_PATH:系统运行程序时,动态库查找的辅助路径

  3. sudo ln -s /xxx

  4. sudo touch /etc/ld.so.conf/myconf.cof
    etc/ld.so.conf/
    这是存放用户自己用的配置文件的目录
    我们就可以在这个配置文件里放入库的路径

补充:ldconfig
意思是让更改的配置文件生效

官方的建议用第一种
自己写的(不成熟的)可以用第三种

补充:编译

gcc默认使用动态库

使用-static 就进行静态链接

只提供静态库的话,虽然是静态链接 但程序整体不一定是静态的

只提供动态库的话,无法静态链接(static)

动态库加载

系统方面

像是可执行程序、库都是磁盘文件 当需要这个库的时候 库的代码和数据会加载到物理内存中,
当某个进程需要的时候 就会被映射到进程的共享区内,

当其他进程需要的时候,同理也是映射到共享区内,这就是动态库(共享库)
那么公共的代码和数据 只需要存在一份

可执行程序

当没加载到内存的时候 可执行程序是有地址的,他们在没有加载之前 已经被按照类别(权限,属性)进行划分

页表(虚拟地址与物理地址)

  1. cpu中 寄存器cr3指向页表,寄存器pc指针保存的正在执行指令的下一条指令
  2. 我们知道可执行程序在磁盘中,他的每一条汇编指令都有自己的逻辑地址(相对地址和绝对地址),大部分操作系统采用的都是相对地址,即0加上偏移量
  3. 而在可执行程序程序的最前面有表头,他写着main函数的逻辑地址,整个程序的区域划分和每个区域的起始地址,方便初始化进程的时候知道要开多大的数据区合适
  4. 而可执行程序在执行的时候,会在物理内存中开辟相应的地址,这时候逻辑地址变为了虚拟地址(在linux中 二者相同
  5. 所以,页表中就是虚拟地址和物理地址的映射

结论:地址空间,是由OS+编译器+计算机体系结构(CPU)共同完成的

静态库的加载

静态库就是把库里的方法直接以绝对编址的方式写到可执行程序里

动态库是如何加载的

库加载的内存时,只记录每条指令的偏移量,起始地址是不固定的(采用相对编址的方式)


http://www.mrgr.cn/news/59846.html

相关文章:

  • 鹏哥C语言95---第17次作业:指针初阶+结构体
  • 最短路径问题的经典算法——Dijkstra[被证明具有普遍最优性(Universal Optimality)]
  • JavaCV 之均值滤波:图像降噪与模糊的权衡之道
  • Python之Excel自动化处理(三)
  • ReactNative 启动应用(2)
  • Java的访问修饰符
  • 快速入门HTML
  • dd命令简介
  • FreeRTOS 6:任务创建函数xTaskCreate分析
  • 用canvas对图片压缩
  • 零基础Java第十一期:类和对象(二)
  • 面试题:ABCD四个线程,A线程最后执行
  • 「C/C++」C++标准库之#include<fstream>文件流
  • Grid View 网格视图
  • 一文带你搞懂RabbitMQ 如何保证消息不丢失
  • 为什么STM32在构建工程时候,没有用到core_cm3.c 只用到了core_cm3.h?
  • 使用AVPlayer进行音频播放开发基础设计
  • 安全运营 -- 监控linux命令history
  • [LVGL] 自定义控件例子
  • Meta分析(荟萃分析)