《计算机组成原理/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 ...
随机推荐
- short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型.而short s1 = 1; s1 += 1;可 ...
- 在JAVA中如何跳出当前的多重嵌套循环?
在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break语句,即可跳出外层循环.
- org.apache.kafka.common.errors.SerializationException: Error deserializing... Caused by: org.apache.kafka.common.errors.SerializationException: Size of data received by IntegerDeserializer is not 4
原因,最近开发的kafka消息接收,突然报如下错: org.apache.kafka.common.errors.SerializationException: Error deserializing ...
- Collection和 Collections的区别?
Collection是集合类的上级接口,继承与他的接口主要有Set和List.Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索.排序.线程安全化等操作.
- 详细描述一下 Elasticsearch 索引文档的过程 ?
这里的索引文档应该理解为文档写入 ES,创建索引的过程. 文档写入包含:单文档写入和批量 bulk 写入,这里只解释一下:单文档写入流程. 记住官方文档中的这个图. 第一步:客户写集群某节点写入数据, ...
- memcached 是怎么工作的?
Memcached 的神奇来自两阶段哈希(two-stage hash).Memcached 就像一 个巨大的.存储了很多<key,value>对的哈希表.通过 key,可以存储或查询任意 ...
- @Qualifier 注解?
当有多个相同类型的 bean 却只有一个需要自动装配时,将@Qualifier 注解和 @Autowire 注解结合使用以消除这种混淆,指定需要装配的确切的 bean.
- 学习Walle(一)
一.概述 Walle 一个web部署系统工具,配置简单.功能完善.界面流畅.开箱即用!支持git.svn版本管理,支持各种web代码发布,PHP,Python,JAVA等代码的发布.回滚,可以通过we ...
- 详解Mysql事务隔离级别与锁机制
一.概述 我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能 就会导致我们说的脏写. 胀读和不可重复读.幻读这些问题. 这些问题的本质都是数据库的多事务并 ...
- 实用的 CSS — 贝塞尔曲线(cubic-bezier)
欢迎移步我的博客阅读:<实用的 CSS - 贝塞尔曲线(cubic-bezier)> 前言 在了解 cubic-bezier 之前,你需要对 CSS3 中的动画效果有所认识,它是 anim ...