《程序员的自我修养》这本书其实最开始是信息安全这门课推荐的书,当时书买了,也看了点,后来就感觉跟没看是一样的,主要是之前根本就没怎么接触,也没写什么读书笔记或者做一些实验来加深对知识的理解,后来上了《程序设计与计算机系统》和《计算机病毒》这两门课,然后再次读了一下,收获颇丰!
这本书的全名叫做《程序员的自我修养---链接,装载与库》,但是不得不提的是编译这个过程也非常重要,书的第二章从一个简单的输出hello,world程序说起
当在linux下面执行gcc hello.c或者在windows下面cl /c hello.c,这个过程实际上可以分为一下4个步骤:
预编译过程主要处理源代码文件中以#开始的预编译指令,比如”#include”, ”#define”,处理规则如下:
编译过程主要是对预处理完的文件进行一系列的词法分析、语法分析、语义分析、代码生成、代码优化最终得到汇编代码。
词法分析:主要是扫描源程序将源代码的字符序列分割成一系列的Token,Token主要分为关键字,标识符,数字,字符串和特殊符号等,在扫描的过程之中也会将标识符加入符号表,数字,字符串常量等放入文字表以备后用。
语法分析:主要对词法分析得到的Token进行上下文无关语法(Context-free Grammar)分析得到语法树,于此同时还会进行语法检查,编译器报告语法分析阶段的错误。
语义分析:主要分为静态语义分析和动态语义分析,主要是确定表达式两边的类型,静态语义分析主要是在编译时期就确定(普通类型),而动态语义分析则是在运行时期进行确定(JAVA中的反射)。
代码生成:主要是将语法树转换成中间代码,比较常见的是三地址码和P代码,代码生成器主要是将中间代码转换成目标机器代码。
当程序经过编译之后生成的机器代码中,有许多定义在其他模块的变量的地址是不知道的,所以这个时候链接器就出现了,链接器主要是将各个模块的代码段和数据段进行合并得到一个可执行的目标文件。链接主要要做两件事情,一件是符号的解析,另外一件事情是地址的重定位,符号的解析主要针对目标文件中的符号的定义和引用分为三种不同的符号:
重定位主要干以下两件事情:
链接主要分为静态链接和动态链接这两种方式:
我认为如果想研究程序的运行环境,首先要知道程序与内存之间的关系,linux下面给进程分配了4G的空间,下图是网上截取的一个详解图:
然后书中讲了栈和调用惯例(calling convention),调用惯例是函数的调用方和被调用方的一个约定,当双方遵循约定时,函数才能正确的被调用,主要是一下几个方面:
在书的末尾还了解到了C运行库的实现,书中运行库主要包括以下几个方面:
书中还夹杂着对windows和linux中的文件格式的对比,windows主要是PE格式,书中提到了Entry point(程序的入口地址),image base(程序装载进进程的基地址)而PE HEADER则是程序载入内存空间头部,头部后面就是大家熟悉的.text段.data段等,以及动态链接的不同之处,windows主要是DLL(这就是为什么system32下面全是dll的原因,这也是为什么你打开word,ppt的时候前面会有一段的延迟时间,主要是在链接DLL),而linux下面主要是使用.so。
在CSAPP的辅助之下,看完这本书之后,自己对程序的编译,链接,装载,运行各个过程有了更深刻的认识,代码指令是如何保存的,库文件如何与应用程序代码静态链接,应用程序如何被装载到内存中并开始运行,动态链接如何实现,C/C++运行库的工作原理,以及操作系统提供的系统服务是如何被调用的,偶尔会从底层思考上层的设计原理和实现机制(java中异常的处理,代码的优化等)。
所以说读完这本书真是受益匪浅啊,自己在学习知识方面也慢慢趋于对知识深层次的理解,深入挖掘问题的本质是什么,而不是像以前那样以为自己懂了,认为自己可以不用看了,但实际上自己可能没真正理解它的真正意思,另外学习知识的过程有时候是一个反复的过程,是一个慢慢咀嚼升华的过程,每一次阅读思考之后,新的理解新的感悟新的收获也会随之而来,我想这也就是学习的乐趣吧!
说句真心话,这P大点文字真心不算读后感,没办法,个人能力问题(贴在这里感觉丢人了),但是待我在看几遍在重新修改这篇文章!
写博客是为了更好的思考,所以让自己成为一个持续学习和思考的人,并只写自己真正思考和总结之后的产物!(这是最近看刘未鹏博客的收获,这段话写在这里来鞭策一下自己吧!)。