《深入理解计算机系统》读书笔记——第7章 链接

前言最近新的一批师弟进实验室了,有几个师弟要做嵌入式开发,需要涉及到第三方库的编译,我已经不止一次听到过师弟问我有关链接的问题了:为什么编译的时候提示函数未定义?明明已经include了头文件,vsc也没有画波浪线呀?为什么提示函数重定义?(一般这种,都是发现include xxx.h不管用,就直接include xxx.c,改一个include没问题,但是把其它文件里的include都改成这样,就会造成这个问题)全局变量应该在哪里定义?extern加在哪里?是的,这些问题中,没有一个提到了“链
摘要由CSDN通过智能技术生成

前言

最近新的一批师弟进实验室了,有几个师弟要做嵌入式开发,需要涉及到第三方库的编译,我已经不止一次听到过师弟问我有关链接的问题了:

为什么编译的时候提示函数未定义?明明已经include了头文件,vsc也没有画波浪线呀?
为什么提示函数重定义?(一般这种,都是发现include xxx.h不管用,就直接include xxx.c,改一个include没问题,但是把其它文件里的include都改成这样,就会造成这个问题)
全局变量应该在哪里定义?extern加在哪里?

是的,这些问题中,没有一个提到了“链接”二字,但是它们的确就是不了解链接原理带来的问题。

这些问题产生之后,我们第一反应就是去百度,去看CSDN博客,看看这个报错是什么意思。但是并不是所有的博文都对症,版本不同、库不同,可能会有不一样的解决方式。对于一些自己编写的程序,在脱离了Visual Studio这种IDE之后,想要把函数写在多个源文件内,就必须对链接的原理有所了解。

由于编译一章十分重要,其它计算机原理不了解只是少吹点牛逼,链接不了解,那别人写的库(甚至自己写的多个源文件)都没法包含到自己的代码中来:(

第七章 链接

链接是将各种代码和数据片段(注意,不只是代码!)收集并组合成一个单一文件的过程。这个文件可以被加载到内存并执行。链接可以发生在编译时(如静态链接库,编译时选择静态链接),也可以发生于加载时(如程序依赖某个动态链接库,也就是编译时的动态链接),甚至发生于运行时(采用加载动态链接库的函数dlopen(),查找指定名称函数并调用,怎么听起来这么像反射机制??)

在现代系统中,链接是由链接器自动执行的。通过理解链接的原理,可以我们有下面的这些帮助:

理解符号引用、符号定义等概念,面对链接器的相关报错,可以知道原因出在哪里,进而思考如何解决;
避免一些链接器发现不了的程序错误,如符号重定义时,链接器的warning,可以帮助我们发现代码中的符号引用错误;
理解语言的作用域规则如何实现,static全局变量和static函数与非static的全局变量和函数的区别何在;
理解与其它操作系统概念的融合,如虚拟内存,程序运行,内存分页;
有助于共享库的使用。

7.1 编译器驱动程序

当我们调用gcc将多个c源文件编译并生成一个输出文件时

gcc main.c sum.c -o main

通常有这些工作:

启动编译器驱动程序,用于驱动下面的执行流程;
1.预处理器(cpp):处理带“#”号的预处理代码,比如include等,生成一个main.i文件;
2.编译器(cc1):将每个源文件都翻译成汇编语言文件(main.s),这个文件是可读的;
3.汇编器(as):将main.s文件翻译成一个可重定位目标文件(main.o);
4.对sum.c重复1~3,生成sum.o文件
5.链接器(ld):将main.o sum.o文件组合起来,创建一个可执行目标文件main。

在执行文件时,shell会调用操作系统的加载器(loader)函数,将可执行文件中的代码和数据都复制到内存,然后将控制转移到这个程序的开头。

看完了编译的过程,我想,最突出的一个问题就是,可重定位目标文件和可执行目标文件,有什么区别?虽然后面会解释这个问题,但是现在可以先用简短的两句话概括一下它们的区别:

一个.c文件对应一个.o文件,而且从上面的过程可以看出,各个.o文件都是由某个.c独立生成的。所以当有多个源文件,而且源文件之间有相互引用时,每个.o文件都只包含自己的代码和数据,以及对外部符号(位于其它.c文件中的全局变量和全局函数)的引用,链接时会将其进行解析并将符号引用转化为真正的符号地址。
每个.o文件内,各个数据段、代码段的偏移量,都是根据当前.o文件计算得出的,在链接成一个文件的过程中,显然要重新安排这些数据和代码的位置

所以重定位的含义是,.o文件内的代码和数据的引用表(等信息)都需要重新进行定位并更新。

7.2 目标文件

目标文件(常常也会成为二进制代码文件等

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值