《计算机组成原理/CSAPP》网课总结(二)——编译原理基础
这部分是四月份的安排,拖到五一放假了,主要是对源码编译过程的一次总结,总的来说,大致可分为预编译、编译、汇编和链接四部分。这里简单记录一下:

一 概述
1、预处理
或者说是预编译,指的是在编译前需要做的一些处理,如宏替换、include替换等等,这部分没什么东西
每一个.c或.cpp源代码文件会生成一个对应的.i文件;
2、编译
编译过程将预处理后的文件生成为.s的汇编文件,汇编文件可用文本编辑器打开查看,里面的汇编代码是直接对应CPU动作的;
3、汇编
汇编过程将.s汇编文件映射为可重定位目标文件, 一般为.o或.obj扩展名。
4、链接
链接阶段是通过链接器将不同的.o文件进行打包,可以理解为单纯的拼接操作,但操作的时候会检查各个实现是否存在。此外,链接可执行文件时还会导入c或cpp的启动相关的必要系统文件,如cruntime等
二 其他相关知识点
在shell中启动可执行文件后,shell会调用操作系统的加载器将可执行文件读入内存,然后将cpu的控制权交给可执行文件,然后开始执行。
可重定位目标文件的基本组成部分如下,链接过程是基于符号完成粘合的,比如a文件中调用了函数f,b文件中定义了函数f,那么链接过程就能正确完成;否则会出现找不到定义的链接错误,同样如果出现重复定义,也会报错。
至于最终生成可执行文件还是库文件,取决于程序员。如果是生成可执行文件,链接器还会链接调用main函数的相关系统文件,这些文件会调用main函数,所以如果源码里面没有实现,就会报“无法解析的外部符号main”,因为连接器找不到main函数的实现。
如果是生成库文件,比如静态库,我们在linxu下可以用命令
ar rcs libstatic.a *.o *.o,这样可以将可重定位目标粘合在一起,在使用的时候,我们只需要include静态库的头文件,使用其中的函数声明,然后再静态链接的时候链接之前生成的libstatic.lib即可,这个时候只有那些使用到的函数定义会被复制到可执行文件中,没有使用的不会复制,当然其他cruntime模块肯定会被链进来,这是默认的。如下图是一个可执行文件所包含的模块,主要分为代码段和数据段,以及其他部分,程序执行时前两部分会加载到内存中,然后跳转到系统函数
_start()处开始执行,_start()函数是C运行时库中定义的,然后_start()调用_libc_start_main(),然后再调用用户代码中的main()函数

- 如下图是可执行文件加载到内存中虚拟地址空间布局,我们在平时写代码的时候,需要理解其中的不同区域的意义:
在linux x86-64系统中,代码段总是从0x400000处开始,这部分是只读的;然后是数据段;接下来是堆内存段,堆内存是从低地址向高地址分配的;然后是一部分为共享库保留的内存区域;然后是栈空间,起始地址是248-1,这是最大合法用户地址,栈的开辟方向是从高到低;在往上,从248开始的地址是为操作系统的代码和数据保留的,对用户代码不可见。

在启动可执行文件后,操作系统会使用地址空间随机化的策略,栈、共享库和堆的运行时地址都会变化,以防止受到攻击。
动态链接库(动态库),一种特殊的可重定位目标文件。生成共享库的方式和静态库类似,linux下编译命令为
gcc -shared -fpic -o libshared.so A.c B.c,这样就可以生成位置无关的动态链接库文件,在使用时,通过命令gcc -o main main.c ./libshared.so完成动态链接,这个动作只会复制符号表和重定位信息。值得一提的是,在windows下,动态库的符号表和可重定位信息单独存放在一个.lib的动态库的导入库文件中,而真正的动态库实现在另一个同名的.dll中,所以在Windows下执行动态链接其实是静态链接导入库的过程。动态链接库的使用,在可执行文件启动时,可执行文件会检查一个名为.interp的section, 里面包含了动态链接器(ld-linux.so)的路径名,启动动态链接器来执行重定位代码和数据的工作,将动态链接的共享库加载到某个内存段,然后重定位可执行文件中由动态库定义的符号引用。完成重定位后再将控制权交还给可执行文件,至此完成动态库的加载和重定位工作,以后动态库的内存位置就固定了。这种动态库方式需要在编译时就链接动态库,在可执行文件开始执行前就要完成加载,这种方式称为动态库的静态加载。
动态库的动态加载,这种技术更加灵活,无需再编译期将动态库链接到应用中,在运行期间加载某个共享库进行使用。linux下可使用
void *dlopen(const char *filename, int flag)进行运行期加载动态库,示例:void* handle = dlopen("./libvector.so", RTLD_LAZY),信号RTLD_LAZY意思是推迟符号解析直到动态库中的代码被调用时。使用动态库的函数的方法:void *dlsym(void* handle, char* symbol),比如说我们蒂阿勇句柄handle指向的共享库中的add(int a, int b)函数,那么add = dlsym(handle, "add")将返回函数add(int a, int b)的地址供使用;最后,调用方法int dlclose(void* handle)可以将动态库关闭(卸载)。
以上做了一个简要总结,这些内容在我们写具体代码时可能不太重视,但是对构建知识体系,处理一些链接bug还是非常重要的。
《计算机组成原理/CSAPP》网课总结(二)——编译原理基础的更多相关文章
- 《计算机组成原理/CSAPP》网课总结(一)
现在是2022年4月17日晚10点,本月计划的网课<csapp讲解>视频课看到了第八章"异常"第三讲,视频讲的很好但更新很慢,暂时没有最新的讲解,所以先做一个简单总结. ...
- python网课自动刷课程序-------selenium+chromedriver
python的强大之处就在于有许多已经写好的功能库提供,这些库强大且易用,对于写一些有特定功能的小程序十分方便. 现在就用pyhton的selenium+谷歌游览器写一个可以自动刷课的程序,以智慧树上 ...
- linux的系统组成和计算机组成原理,linux常用操作
Linux入门 linux简介 学习目的:linux服务器操作系统稳定长期运行,python,pycharm装于linux上 linux系统组成 应用软件:调用系统软件接口 linux操作系统分两 ...
- Linux内核学习期末总结(网课)
标签(空格分隔): 20135321余佳源 余佳源(原创作品转载请注明出处) <Linux内核分析> MOOC课程http://mooc.study.163.com/course/USTC ...
- 计算机组成原理(电脑硬件&语言分类)
计算机组成原理 一.电脑硬件配置 CPU :中央处理器(人类的大脑) -飞机 内存:存放一些临时数据(人类的短暂记忆-右脑) -高铁 硬盘:存储永久数据(左脑-长期记忆) - 汽车 输入输出:键盘鼠标 ...
- Stanford公开课《编译原理》学习笔记(1~4课)
目录 一. 编译的基本流程 二. Lexical Analysis(词法分析阶段) 2.1 Lexical Specification(分词原则) 2.2 Finite Automata (典型分词算 ...
- 推荐书单(网课)-人生/编程/Python/机器学习-130本
目录 总计(130本) 一.在读 二.将读 三.已读 非专业书单(77本) 四.已读 专业书单(53本) 五.已看网课(8个) 六.在看网课 一个人如果抱着义务的意识去读书,便不了解读书的艺术.--林 ...
- 《数据结构》《C++程序设计》《计算机组成原理》中的英语名词
一.数据结构 data 数据data element 数据元素data item 数据项data object 数据对象data structure 数据结构ADT (Abstruct Date Ty ...
- 《计算机组成原理 》& 《计算机网络》& 《数据库》 Roadmap for self-taugh student
计算机组成原理: UCB的这门课绝对是不错的资源. Great Ideas in Computer Architecture (Machine Structures) B站:https://www.b ...
随机推荐
- Oacle 插入多条记录的语法理解;INSERT ALL INTO ....... SELECT 1 FROM dual;
单表Insert into的语句就不说了,这里主要说插入多条语句的说明 For a multitable insert operation, each expression in the values ...
- try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在方法返回调用者前执行.
- Kafka新建的分区会在哪个目录下创建?
在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性 ...
- 用 Java 写一个折半查找?
折半查找,也称二分查找.二分搜索,是一种在有序数组中查找某一特定元素的搜索算法. 搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束:如果某一特定元素大于或者小于中间元素,则 ...
- 面试问题之C++语言:面向对象的三大特性
转载于:https://www.cnblogs.com/BEN-LK/p/10720249.html 面向对象的三大特性:封装.继承.多态 封装:就是把客观事物封装成抽象的类,并且类可以把自己的数据和 ...
- Spark学习摘记 —— Pair RDD转化操作API归纳
本文参考 参考<Spark快速大数据分析>动物书中的第四章"键值对操作",由于pair RDD的一些特殊操作,没有和前面两篇的API归纳放在一起做示例 前面的几个api ...
- TCP 重传、滑动窗⼝、流量控制、拥塞控制
重传机制 TCP 会在以下两种情况发⽣超时重传: 数据包丢失 确认应答丢失 重传超时 重传超时是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果 ...
- Java中final的使用
原文链接https://www.cnblogs.com/dolphin0520/p/10651845.html 作者Matrix海 子 本文为笔记 0. 概述 final和static一样都是修饰词, ...
- 判断集合中存在String字符串 或 判断集合中不存在String字符串
一.使用场景 用于集合中有多个相近的字符,无法使用包含判断 如: 这里如果我想判断以上集合中是否包含"信封件-DE"就会被"信封件-DE2"影响到 毕竟:&qu ...
- canvas元素内容生成图像文件
准备工作 想要将canvas元素当前显示的内容生成为图像文件,我们首先要获取canvas中的数据,在HTML5 <canvas>元素的标准中提供了toDataURL()的方法可以将canv ...