今天是个好天气 logo 今天是个好天气
  • Home
  • Go
  • MySQL
  • Redis
  • LeetCode
  • Hello World
↩️README 网络发展过程 键入url到渲染显示 HTTP报文 HTTPS / HTTP1、2、3 三次握手/四次挥手 socket 可靠的TCP IP知识全家桶 ping的工作原理 优化程序性能 存储器 链接 进程、线程、调度 问题 虚拟内存 配个环境 Git Shell Docker python

链接

For what

学习链接为了:

  • 构造大型程序
    • 每次编译只需要编译更改的程序
    • 再进行链接
  • 避免一些危险的编程错误
  • 理解语言的作用域如何实现的
  • 理解其他重要的系统概念
  • 更好的利用共享库

可重定位目标文件

image-20230225161144829

gcc -Og -o prog main.c sun.c

-Og 生成的汇编的代码尽可能与源代码一致性,实际中一般用-O1,-O2

cpp -o  main.i main.c
gcc -E -o main.i main.c
//cpp = c comiler(C 编译器)
//-E只进行预处理,不执行编译链接部分

cc -S -o main.s main.i
gcc -S -o main.s main.i
//cc = c compiler
//-S只进行编译操作

as -o main.o main.s
//as: assembler(汇编器)

ld -static -o prog main.o sum.o
//ld 链接器
  • 在实际中链接这个过程,可能发生在多个过程当中。

  • 在shell中调用操作系统中一个叫做加载器loader的函数,它将可执行文件prog中的代码和数据复制到内存当中,然后将控制转移到这个程序的开头。

gcc -c main.c
    
readelf -h main.o
//读取ELF Header

目标文件中存放了代码和数据,具体总结下里面的内容。

符号表

符号表是ELF头文件其中的一个节。

通过objdump和readelf查看二进制文件。

利用符号表中的信息,进行链接的有关操作。

.bss和COMMON中分配的符号区别

静态链接

为了构造可执行文件,链接器必须完成两个主要任务:

  • 符号解析:将目标文件中定义和引用的符号,每个符号与对应的函数、全局变量或者一个静态变量相关联起来
  • 重定位:编译器和汇编器将从地址0开始生成代码和数字节,将每部分代码与内存位置对应关联起来,修改所有对这些符号的引用,指向相应的内存地址。

与静态库链接

如果把所有标准C函数放在一个目标文件中,那么每个程序都需要一个标准函数的副本,这是一种内存浪费。

如果为每个函数都单独创建一个独立的可重定位的文件,把他们存放在一个文件中,对每一个单独文件的链接又会耗费大量时间,也有可能出错。

因此引出了静态库这一个概念,把相关函数封装成一个静态库。链接库会从其中复制使用到的相关模块到可执行文件当中。这样减少了不必要的模块的内存占用。

注意链接静态库的顺序,静态库文件一般放在最后。

重定向

动态链接

为了解决了静态库的更新问题以及重复代码复制到每个进程中占据过大的内存问题,有了动态链接库。

区别静态库链接,在链接阶段只进行了重定向、提取了符号表信息,等到加载到内存执行时,通过动态链接器从动态链接库中重定位文本和数据到内存当中。

这样实现了不同正在运行的进程共享动态链接库。

  1. For what
  2. 可重定位目标文件
  3. 符号表
  4. 静态链接
    1. 与静态库链接
  5. 重定向
  6. 动态链接
Created by shixiaocaia | Powered by idoc
Think less and do more.