首页 > 代码库 > 读书笔记:程序员的自我修养-----第一章(综述)

读书笔记:程序员的自我修养-----第一章(综述)

题前:30--45天读完,一周至少3篇读书笔记。不能坚持,不再联系,不再找你。

一. hello world 程序引出的问题,看40天后,再回来看看自己的答案,提升多少。

  Q1:程序为什么要被编译器编译之后才可以运行?

     A1 : 系统执行的机器语言,即二进制文件,程序是文本文件需要编译之后,由链接器链接需要的基本库生成二进制文件.

       Q2: 编译器在把C语言程序转换成可以执行的机器码的过程中作了什么,怎么做的?

    A2: 预处理,汇编器生成汇编文件,编译器生成目标文件,链接器链接生成可执行文件

    Q3: 最后编译的可执行文件里是什么?除了机器码还有什么?它们怎么存放的,怎么组织的?

  A3: 可执行文件里面是机器码,除了机器码还有什么?   未知。 组织: bss,data, code,这个遗忘了

  Q4: #include<stdio.h>是什么意思? 把stdio.h包含进来意味着什么?C语言库又是什么?它是怎么实现的?

  A4: 在预处理时,会把stdio.h头文件里的程序语句加到源文件里。把stdio.h包含进来意味着可以使用在stdio.h里声明的库函数。

      C语言库是为了方便程序员,而提供的基本的诸如I/O,字符处理的库函数. 怎么实现?通过动态或静态编译实现的.不知对否.

  Q5: 不同的编译器和不同的硬件平台以及不同的操作系统,最后编译的结果一样吗?为什么?

  A5: 不同的编译器因为处理(具体什么处理,不清楚)不同,所以接过不一样;不同的硬件平台因为指令结构不同,处理接过也不一样;

        不同的操作系统因为二进制格式不一样,所以编译出来的接过不一样.

  Q6: Hello World是怎么运行起来的?操作系统是怎么装载它的?它从哪儿开始执行,到那儿结束?main函数之前发生了什么?main函数结束以后发生什么?

       A6: 操作系统加载到内存,找到程序入口地址,开始运行;怎么装载,未知;起于何处,至于何处未知?main函数前后发生什么未知.

  Q7: 如果没有操作系统, Hello World可以运行吗?如果要在一台没有操作系统的机器上运行Hello World需要什么?应该怎么实现?

  A7: 需要去掉可执行程序的头部格式(具体怎么做,忘了),然后在处理程序的时候指定加载内存的addr,然后加载到这个addr,执行。

  Q8: printf 是怎么实现的?它为什么可以又不定数量的参数?为什么它能够在终端上输出字符串?

  A8: printf 是通过调用系统调用write实现的,不定数量的参数依赖于stdarg.h,具体实现未知,因为终端输出也是作为文件描述符处理。

  Q9: Hello World 程序在运行时,它在内存中是什么样子的?

  A9: 应该是映射在物理内存的一块地方,未知.

       通过回答这些问题,自己才意识自己基础多么薄弱.

二. 计算机系统软件体系结构采用一种层的结构

  “Any proble in computer science can be solved by another layer of indirection."

       这让自己之前写的一个线程池,朋友看后鄙视我好久,认为内聚性太低,当时我承认,可我也同时儿认为我这通用性强。

        我那线程池不能作为一个接口,所以只能算dogshit.

三. 为什么要分段分页

     解决内存使用的三个问题:

  1. 地址空间不隔离

  2. 内存使用率低

  3. 程序运行地址不确定

     分段通过虚拟地址映射,解决1,3

      分页解决2

四. 线程基础

     一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成。共享(代码段,数据段,堆,以及一些进程极资源)

     分类: I/O密集型线程,CPU密集型线程。前者一般优先级高

     优先级改变方式:

  1. 用户指定优先级

  2. 根据进入等待状态的频繁程度提升或降低优先级

  3. 长时间得不到调度提升

五. 线程安全

  1. 线程同步

             原子操作,锁(二元信号量,互斥量,临界区,读写锁,条件变量)

             信号量在整个系统中可以贝任意线程获取并释放,互斥量只能被获取的线程释放;临界区的作用范围仅限于本进程,互斥量在系统任何进程中可见,

  除此,具有相同性质;条件变量类似与一个栅栏,线程可以一次唤醒一个或所有等待线程。应用如:线程池

  2. 可重入与线程安全

         @1:线程可重入情况:

      多个线程同时执行这个函数

      函数自身(可能经过多层调用之后)调用自身。

    @2:可重入条件:

      不使用任何(局部)静态或全局的非const变量

      不返回任何(局部)静态货全局的非const变量

      仅依赖调用方提供的参数

      不依赖任何单个资源的锁

      不调入任何不可重入的函数

  3. 过度优化

    @1: 保护区域数据因编译过度优化,存放到寄存器中

    @2:编译器为了提高效率,调整两条互不影响相邻指令的执行顺序

         使用volatile可以组织变量缓存到寄存器而不被写回,也可以组织编译器调整操作volatile变量的指令顺序,但不能阻止CPU动态调度程序.

    C++ new的两个步骤:分配内存,调用构造函数

六. 线程模型

  1.  一对一模型

  2. 多对一模型

  3 .多对多模型

  linux 内核线程和用户线程?