第一部分:温故而知新
第一章:介绍基本的背景知识——操作系统、线程、硬件

1、关于C语言中的hello world这些问题你都清楚吗?

2、计算机硬件设备的三个核心部件:
1》中央处理器CPU
2》内存
3》I/O控制芯片

3、
1》开发工具与应用层是属于同一个层次的,因为他们都使用同一个接口,那就是——应用程序编程接口(API——Application Programming Interface)
2》而应用程序接口的提供者是运行库。
3》运行库使用操作系统提供的系统调用接口。
4》系统调用接口在视线中往往以软件中断的方式提供

4、操作系统的功能:
1》提供抽象接口。
2》管理硬件资源

5、多道程序——》分时系统——》多任务系统(CPU采用抢占式分配方式)

6、线程:
1》线程,有时候被称为轻量级进程(LWP),是程序执行流得最小单元。
2》一个标准的线程由线程ID、当前指针指令(PC)、寄存器集合、堆栈组成
3》通常,一个进程由一个到多个线程组成,各线程之间共享程序的内存空间(包括代码段、数据段、堆等)以及一些进程级的资源(如打开文件和信号)

7、二元信号量:
1》二元信号量是一种最简单的锁。它只有两种状态:占用和非占用。
2》它适合只能被唯一一个线程独占访问的资源,当二元信号处于非占用状态时,第一个试图获取该二元信号量的线程会获取该锁,并将二元信号量置为占用状态,以后其他的所有试图获取该二元信号量的线程将会被等待,直到该锁被释放。

8、volatile关键字:
1》阻止编译器为了提高速度将一个变量缓存到寄存器内而不写回。
2》阻止编译器调整volatila变量的指令顺序
3》volatile虽然能够阻止编译器调整顺序,但是无法阻止CPU动态调度换序。

8+、单例模式:Singleton
1》单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。
2》通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约资源。
3》如果希望在系统中的某个类的对象只能存在一个,单例模式是最好的解决方案。

9、一个类只能创建一个对象

class Singleton
{friend Singleton* CreateObj();friend void ReleaseObj();
private:Singleton(){cout << "Singleton()" << endl;}~Singleton(){cout << "~Singleton()" << endl;}
private:int data;static Singleton* pObj;static std::mutex _mutex;
};
Singleton* Singleton::pObj = NULL;
std::mutex _mutex;Singleton* CreateObj()
{if (Singleton::pObj == NULL ){_mutex.lock();if (Singleton::pObj == NULL ){//线程同步//std::_Mutex mutex;//互斥量Singleton::pObj = new Singleton;}_mutex.unlock();}return Singleton::pObj;
}
void ReleaseObj()
{if (Singleton::pObj != NULL ){delete Singleton::pObj;Singleton::pObj = NULL;}
}

10、另一个著名的与换序有关的问题:Singleton模式的double-check.
一段经典的代码:

volatile T* pInst=0;
T* GetInstance( )
{if(pInst == NULL){lock( );if(pInst == NULL){pInst = new T;}unlock( );}return pInst;
}

——当函数返回时,pInst总是指向一个有效地对象。而lock 和 unlock防止了多线程竞争的问题。
——双重if可以让lock的调用开销降低到最小。
但是:实际上这段代码是有问题的,问题来源于CPU的乱序执行。
1》C++里的new包含了两个步骤:分配内存 、 调用构造函数
2》所以pInst = new T也包含了三个步骤:1分配内存 、2在内存的位置上调用构造函数 、3 将内存的地址赋值给pInst。
3》在上面的三步中,2 3 的顺序是可以颠倒的。也就是说完全有可能出现这样的情况:pInst的值已经不是NULL了,但是对象还没有构造完。这时候,如果出现另外一个对GetInstance的并发调用,此时第一个if内的表达式pInst == NULL 为false,所以这个调用会直接返回尚未构造完的对象的地址已提供给用户使用,那么程序就有可能崩溃。

11、内存屏障——barrier指令
1》内存屏障,也称内存栅栏、屏障指令,是一类同步屏障指令,使得CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作。
2》大多数现代计算机为了提高性能而采取的乱序执行,这使得内存屏障成为必须。
3》语义上:内存屏障前的所有写操作都要写入内存;内存屏障之后的读操作都可以获得同步屏障之前的写操作的结果。
4》因此,对于敏感的程序块,写操作之后、读操作之前可以插入内存屏障。

12、许多体系结构的CPU都提供barrier指令,不过它们的名称各不相同,例如POWERPC提供的其中一条指令名叫lwaync。
我们可以这样保证线程安全:

#define barrier( ) _asm_ volatile ( "lwaync")
volatile T* pInst=0;
T* GetInstance( )
{if(pInst == NULL){lock( );if(pInst == NULL){T* temp = new T;barrier( );pInst = temp;}unlock( );}return pInst;
}

——由于barrier的存在,对象的构造一定在barrier执行之前完成,因此当pInst被赋值时对象总是完整的。

第二部分:静态链接
第二章:编译和链接

1、一个 Hello World 程序 需要完成四个步骤:分别是 预处理(Prepressing) 、编译(Compilation) 、汇编 (Assembly)、和链接(Linking)

2、

3、预编译:
1》首先是源代码文件helloc.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个 .i 文件。对于C++程序来说,它的源代码文件的扩展名可能是 .cpp 或 .cxx ,头文件的扩展名可能是 .hpp ,而预编译后的文件按扩展名是 .ii 。
2》第一步预编译的过程相当于如下的命令(-E表示只进行预编译):
gcc−Ehello.c−ohello.i或者 gcc -E hello.c -o hello.i 或者 gcc hello.c > hello.i
3》预编译过程主要处理那些源文件代码中的以“#”开始的预编译指令,比如“#include”、“#define”等,主要处理规则如下:
1>将所有“#define”删除,并展开所有的宏定义。
2>处理所有条件预编译指令,比如:“if”、“ifdef”、“elif”、“else”、“endif”
3>处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。
4>删除所有的注释“//”和“/* */”.
5>添加行号和文件标识,比如#2 “hello.c” 2,以便于编译时编译器产生调试用的行号信息以及用于编译时产生的编译错误或者警告时能够显示行号。
6>保留所有#pragma 编译器指令,因为编译器需要使用它们。
4》经过预编译之后的 .i 文件不包含任何宏定义,因为所有的宏都已经被展开了,并且包含的文件也已经被插入到 .i 文件中。所以当我们无法判断宏定义是否正确或头文件包含是否正确时,可以查看预编译后的文件来确定问题。

4、编译:
1》编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后产生相应的汇编代码文件,这个过程往往是我们所说的整个程序构建的核心部分,也是最复杂的部分之一。
2》上面的编译过程相当于如下命令: gcc−shello.i−ohello.s或者 gcc -s hello.i -o hello.s 或者gcc -s hello.o -o hello.s
3》实际上gcc这个命令只是这些后台程序的包装,它会根据不同的参数要求去调用预编译编译程序cc1、汇编器as、链接器ld

5、汇编:
1》汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。所以汇编器的汇编过程相对于汇编器来讲比较简单,它没有复杂的语法,也没有语义,也不需要指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。
2》上面的汇编过程我们可以调用汇编器as来完成: ashello.s−ohello.o或者 as hello.s -o hello.o 或者 gcc -c hello.s -o hello.o 或者使用gcc命令从C源代码文件开始,经过预编译、编译、汇编直接输出目标文件 $gcc -c hello.c -o hello.o

6、链接:

7、编译器:
编译器的作用:从最直观的角度来讲,编译器就是将高级语言翻译成机器语言的一个工具。比如我们用C/C++语言写的一个程序可以使用编译器将其翻译成机器可以执行的指令及数据。

8、编译过程:
1》编译过程一般分为6步:扫描、词法分析、语义分析、源代码优化、代码生成、和目标代码优化
2》整个过程如下图:

9、词法分析:首先源代码程序被输入到扫面器(Scanner),扫描器的任务很简单,它只是简单的进行词法分析,运用一种类似于有限状态机(Finite State Machine)的算法可以很轻松的将源代码的字符序列分割成一系列的记号(Token)。

10、语法分析:接下来语法分析器(Frammar Parser)将对扫描器产生的记号进行语法分析,从而产生了语法树。整个分析过程采用了上下文物管语法的分析手段。

11、语义分析:语义分析是由语义分析器来完成的。

程序员的自我修养——读书笔记相关推荐

  1. 程序员的自我修养读书笔记-1

    前序:作为一个马上就要工作的非科班本科生,前段时间为了找工作,有针对性的学习了一些编程语言,数据结构,网络方面的知识,学的非常浅,非常杂乱,存粹是为了应对找工作.现在空下来了,想着以后应该就是走程序员 ...

  2. 程序员的自我修养 - 读书笔记文字版

    第1部分 简介 第1章 温故而知新 程序在运行的时候先通过分段(segmentation)的方式将虚拟地址空间与真实的物理内存地址空间进行一一的映射,但是这种方式每次换入换出的是整个程序,导致IO变大 ...

  3. 程序员的自我修养阅读笔记

    编译和链接 将编译和链接合并到一起的过程称为构建(Build). 从源文件生成最终可执行目标文件共有4个步骤: 预处理(Prepressing) 编译(Compilation) 汇编(Assembly ...

  4. 程序员的自我修养——学习笔记1

    文章目录 计算机硬件 早期计算机 发展 SMP和多核 计算机软件 操作系统和设备驱动的作用 文件系统 存储设备 未使用内存管理时 解决思路:地址空间 分段 分页 线程进程 参考资料 计算机硬件 计算机 ...

  5. 程序员的自我修养学习笔记——第五章

    PE: Portable Executable COFF: Common Object File Format 跟ELF一样,PE中也允许程序员将变量后函数放到自定义段.在GCC中使用"__ ...

  6. 《程序员的自我修养》笔记

    第1章 引言 说明:①本书中将计算机的范围限定于PC机,更具体的讲是采用x86指令集的32位CPU的个人计算机. 1.1 CPU与外围部件的连接方式 计算机最核心的三个硬件设备是:CPU.内存.I/O ...

  7. 【读书笔记】程序员的自我修养总结(七)

    [读书笔记]程序员的自我修养总结(七) 标签: [编程开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:这是程序员的自我修养一书的读书总结,随着阅 ...

  8. 【读书笔记】程序员的自我修养总结(一)

    程序员的自我修养总结(一) 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:这是程序员的自我修养一书的读书总结,随着阅读的推进,逐步增加内容. 1. 关 ...

  9. 读书笔记程序员的自我修养 0

    读书笔记<<程序员的自我修养>> 0 为什么要读这本书? 可能因为自己是读硬件的缘故,对于编程,我总是尝试的了解各种表象的下面发生了什么事情.而困扰了我的许多问题,在这本书上都 ...

最新文章

  1. 白平衡——图像处理中的一种增强技术
  2. 深度图像分割 -- Fully Convolutional Networks for Semantic Segmentation
  3. phoneGap+jquery mobile项目经验
  4. 解决RedHat中ifconfig命令不能使用的问题
  5. WEB前端笔试题(4)
  6. debian 文件夹中文件大小_Linux下查看文件和文件夹大小 删除日志
  7. ESP32 OTA升级框架
  8. 【不屈】生如蝼蚁,当立鸿鹄之志
  9. 中国人工智能学会通讯——神经环路研究最新进展及对类脑计算的启示 1.复杂科学...
  10. 机器学习笔记:PCA的简单理解以及应用建议
  11. python scikit learn 关闭开源_慕课|Python调用scikit-learn实现机器学习(一)
  12. 提花织机行业调研报告 - 市场现状分析与发展前景预测
  13. Unity3D基础39:人物角色模型
  14. [Linux]如何读取Kernel cmdline
  15. 算法萌新如何学好动态规划(三)
  16. 初中计算机excel考试系统,基于Excel构建计算机考试系统
  17. Ubuntu交叉编译工具链安装
  18. 打包一个包含手表端应用的手机端APK应用—Ticwear
  19. 一文读懂嵌入式FPGA,改变芯片设计方式岂是闹着玩的
  20. Pytorch使用VGG做迁移学习(基于 CIFAR100 数据集)

热门文章

  1. 小故事——巴比奇和他的计算机
  2. 基于NEO4J图模型的关系计算
  3. Java老矣,尚能饭否?——Stack Overflow 2018 开发者调查报告出炉
  4. 教你如何显示隐藏文件
  5. python扩展库xlwt支持对excel_Python扩展库xlwt支持对Excel2003或更低版本的Excel文件进行写操作。...
  6. Spark SQL 外部数据源
  7. 微信小程序开发—小程序开发入门
  8. 流放者柯南联机显示无法链接服务器,《流放者柯南》联机疑难问题解答
  9. gitbook 安装
  10. attach和detach区别