读书笔记-3 《程序员的自我修养》

读书笔记3—《程序员的自我修养》

《程序员的自我修养》这本书主要介绍系统软件的运行机制和原理,主要包括一个应用程序在编译、链接和运行时刻所发生的各种事项,例如代码指令如何保存、动态链接如何实现等。我结合目前的需求,主要阅读了本书中关于线程、编译与链接、装载与进程以及API的章节,受益匪浅且感触颇多,本篇笔记可能概括不完,希望下周可以继续阅读此书并续写笔记。

  线程,也称轻量级进程,是程序执行流的最小单元。一个标准的线程通常由线程ID、当前指令指针PC、寄存器集合和堆栈组成;一个进程由以或多个线程组成且各线程共享程序的内存空间。多数应用程序都不止一个线程,事实上多个线程之间互不干扰,可以并发执行以及共享进程的全局变量和堆的数据。而多线程的优势主要在于提高工作效率,例如当某个操作陷入长时间等待时,就十分有必要用其他线程来充分利用等待时间,典型的例子就是等待网络响应。而各线程之间也不是完全共享信息的,比如局部变量、TLS数据就是线程私有的。既然有多个线程,我们怎么充分利用他们呢?事实上操作系统会让他们轮流执行,但每次仅执行很小一段时间(几十到几百微秒),这种在处理器上不断切换线程的行为称作线程调度,这也是其意义所在。

此外本书还介绍了多线程的三种模型,一对一、多对一和多对多,一对一模型是最简单的模型,由于用户使用的线程与内核的线程是一一对应的,所以线程之间的并发是真正的“并发”,互不影响;多对一则是将多个用户线程对应到一个内核线程上,优点就在于线程切换要快很多,多对多则是上述二者的结合,具有更为广泛的应用。

前几天用贪吃蛇实例总结java基础的时候第一次接触到线程的概念,java提供了Thread类来支持多线程程序,此例中,贪吃蛇的运动与接收用户输入改变其方向就应分为两个线程,让二者交替执行,这是一个多线程的典例,我也是看了本书后才理解其含义。

  编译和链接,这是每个接触过编程的人最熟悉不过的概念了,从helloworld开始我们就记住了代码写完之后要结果编译、链接之后才能运行,之后用单片机就多出了最后一步烧写,其实上述过程可以细分为预处理、编译、汇编和链接四个步骤,当然这里我只是借此书略微了解一下过程,真正要掌握还得等以后的编译原理课程了。

首先是预编译,主要是处理源文件中以#开始的预编译命令,例如#include、#define等,规则主要有:展开所有的宏定义、处理条件预编译命令比如#if、#ifdef这些、处理#include命令、删除所有注释、添加行号和文件名标识(以便于编译器产生调试用的行号以及返回错误信息)以及保留#pragma命令。

其次是编译过程,其实就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件,这是整个程序构建的核心部分,也是最复杂的部分之一。一般可以分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化(如附图所示)。

然后是汇编,也就是将汇编代码转变为机器可以执行的指令。这一过程相对于编译来说比较简单,根据汇编指令与机器指令的对照表一一翻译就可以了。

最后则是链接过程,主要内容就是把各个模块之间相互引用的部分都处理好,使得他们之间可以正确地衔接从而完成程序的功能,包括地址和空间分配、符号决议和重定位这些步骤,简而言之就是还原一些指令对其他符号地址的引用,使得程序按照正确的流程运行。

当然我们使用的IDE集成开发工具和编译器默认的命令通常会将这四步合并,所以我们一般不会关注他们。

本次笔记内容不是很多,但确实是深有感触,所以写的详细一点,可能语言上的赘述有不少,敬请谅解。

 

posted @ 2018-03-18 00:01  千里目对一层楼  阅读(136)  评论(0编辑  收藏  举报