《深入理解计算机系统》阅读笔记--计算机系统漫游

《深入理解计算机系统》,这本书,我多次想要好好完整的读一遍,每次都是没有坚持下去,但是作为一个开发者,自己想要成为为数不多的大牛之一,所以打算这次把这本书完整的好好读一遍,并整理为相关的博客!

书的开头说了一句话:计算机系统是由硬件和系统软件组成,他们共同工作来运行应用程序。 我们通常接触更多的是应用程序级别的,很少关注系统以及系统和硬件的交互,但是如果自己能完全理解计算机系统以及它对应用程序的影响,那将会让我们在软件开发的路上走的更远,也同时可以避免很多问题的发生。

拿最简单的hello.c 程序来说,我们看到的代码文件内容是:

#include <stdio.h>

int main()
{
    printf("hello,world\n");
    return 0;
}

但是对计算机来说其实就是由0和1组成的位(比特)序列,8个位组成一组,成为字节。

C程序的编译过程

通常我们写完C程序的代码,都会对程序进行编译,将代码文件编译成可执行程序,也就是我们在windows上通常看到的.exe文件,在Linux系统上我们通常通过gcc 来将c代码进行编译,其实当我们通过gcc 编译的时候,执行了四个阶段:预处理阶段,编译阶段,汇编阶段,链接阶段 执行这四个阶段的程序为:预处理器,编译器,汇编器,链接器,一起构成了编译系统 如下图是编译的过程表示:

预处理阶段:其实这个类似python中的import导入,将你要导入的代码文件放到这个文件中,而在C语言中,这里还是以hello.c 为例子,第一行的#include <stdio.h> 会告诉预处理器(cpp)读取系统的头文件中stdio.h的内容,并把它插入到程序文本中,结果是得到了另外一个C程序,生成的文件是以.i结尾

编译阶段:编译器(ccl) 将hello.c 翻译成hello.s ,成为一个汇编语言程序

汇编阶段:汇编器(as)将hello.s 翻译成机器指令,把这些指令打包成一个可重定位目标程序的格式,并将结果保存在hello.o中,hello.o文件其实已经是一个二进制文件。

链接阶段: 我们通常在代码中都会调用到标准库中的一些函数,就像我们hello.c代码中我们调用了printf函数,其实printf函数存在于一个名为printf.o 的单独预编译好的目标文件中,连接器ld 其实就是讲这个文件合并到我们的hello.o程序中。最终得到我们编译好的hello文件中或hello.exe 文件中,这就成了我们通常看到的可执行文件

了解这个编译过程对我们写代码来说的好处:

  1. 优化程序性能
  2. 理解链接时出现的错误
  3. 避免安全漏洞

系统硬件的组成

总线

 我们从上图可以看出,整个系统是通过各种总线在连接,包括了:I/O总线,内存总线,系统总线

通常总线被设计成传送定长的字节块,也就是字(word),现在大多数及其的字长要么是4个字节(32位),要么是8个字节(64位),当然64为居多。

I/O设备

这个我们就比较熟悉了,主要就是用于系统和外部进行交互的,入鼠标键盘,显示器等

每个I/O设备通过一个控制器或适配器与I/O 总线相连。

控制器和适配器的区别:就是封装方式,控制器是主板上的芯片组,而适配器是一个插在主板插槽上的卡,如独立显卡和声卡等

主存

主存是一组动态随机存储器DRAM 芯片组成

主存是一个临时存储设备,用来存放程序和程序处理的数据

处理器

CPU 是解释或执行存储在主存中指令的引擎

处理器的核心是一个大小为一个字的存储设备或者寄存器,称为程序计数器(PC)

寄存器文件是一个小的存储设备,由一些单个字长的寄存器组成,每个寄存器都有唯一的名字,算数/逻辑单元(ALU)计算新的数据和地址。CPU 可能执行的操作:

加载: 从主存复制一个字节或者一个字到寄存器,以覆盖寄存器原来的值

存储: 从寄存器赋值一个字节或者一个字到主存的某个位置,以覆盖这个位置原来的内容

操作: 把两个寄存器的内容复制到ALU,ALU对这两个字做算数运算,并将结果放到一个寄存器中,覆盖该寄存器中原来的值

跳转:从指令本身中抽取一个字,并将这个字复制到程序计数器PC中,以覆盖PC中原来的值

上面大致理解了系统的各个组成部分,这次在回头看hello程序运行时在各个组件中传递过程

当我们开始通过键盘输入hello命令,程序就字符被逐一读到寄存器,然后放到内存中

回车之后系统将磁盘上我们的程序文件加载到主存中,然后处理器就会开始执行程序中的机器指令,并最终在显示器显示hello world

高速缓存的重要性

其实通过上面也看到了系统花费了大量的事件在各个组件之间拷贝来拷贝去,其实这些拷贝也是一种开销

并且在不同设备上运行的速度也是相差非常大,一般来说较大的存储设备要比较小的存储设备运行的慢,但是快速设备的造价会高很多比低速设备,这里就诞生了告诉缓存存储器cache memory

现在的处理器一般有三级高速缓存:L1,L2,L3, 当然可能更多

而这种高速缓存用的是一种叫做静态随机访问存储器(SRAM)的硬件技术实现的

这样就有了下面这个存储设备的层次结构:

存储器层次结构的主要思想是上一层的存储器作为低一层存储器的缓存

操作系统

当我们这会在回头来看操作系统,其实操作系统就是应用程序和硬件之间的中间层,应用程序通过操作系统来对硬件进行操作

操作系统的作用:防止硬件被失控的程序滥用;向应用程序提供一种机制用于操作硬件

而实现这两个功能是通过几个基本的抽象概念来实现:进程,虚拟内存和文件

文件是对I/O设备的抽象,虚拟内存是对主存和磁盘I/O 设备的抽象,进程则是对处理器、主存和IO设备的抽象

这里有几个关键词的概念需要理解:

进程:进程是操作系统对一个正在运行的程序的一种抽象。

并发运行:一个进程的指令和另外一个进程指令是交错执行

操作系统实现叫做执行的机制成为上下文切换

操作系统保持跟踪进程运行所需要的所有状态信息,就是上下文

其实我们在shell命令下执行我们的hello程序就是个并发的场景,这里有两个进程:shell进程和hello进程,而执行的过程可以通过如下图表示:

这里也要知道从一个进程到另外一个进程是有操作系统内核管理的,内核代码是操作系统代码常驻主存的部分

注意:内核不是一个独立的进程。它是系统管理全部进程所用代码和数据结构的集合

线程:一个进程通常可以由多个线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据

虚拟内存:虚拟内存是一个抽象概念,为每个进程提供了一个假象,好像每个进程都在独占的使用主存,每个进程看到的内存都是一致的,称为虚拟地址空间。下图是Linux的虚拟地址空间,地址是从下往上增大

这里先简单的对着几个概念进行理解:

堆:代码和数据区在进程一开始运行就被指定了大小。同时堆可以在运行时动态的扩展和收缩

共享库: 在地址空间的中间部分是一块用来存放C标准库数学库这样的共享库代码和数据区域

栈:位于用户虚拟地址空间顶部的是用户栈,编译器用它实现函数的调用,同样栈在程序执行期间也可以动态的扩展和收缩

如:当我们执行函数时,栈就会增长,一个函数返回时,栈就会收缩

内核虚拟内存:地址空间的顶部区域是为内核保留的,不允许程序血祸者调用内核定义的函数,必须由内核来执行这些操作

Amdahl 定律

该定律的主要思想:当我们对系统的某个部分加速时,其对系统整体性能的影响取决于该部分的重要性和加速度

书中有个例子非常贴切,系统的某个部分的耗时比例是60%,也就是a = 0.6  其加速比例因子为3 k=3,我们可以获得的加速比为:

1/[0.4+0.6/3] = 1.67倍,即使对着一个部分做了重大概念,但获得系统加速比却明显小于这部分的加速比,所以想要显著加速整个系统,必须提升全系统中相当大的部分的速度

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

谷歌发布的首款基于HTTP/2和protobuf的RPC框架:GRPC

Google 刚刚开源了grpc,  一个基于HTTP2 和 Protobuf 的高性能、开源、通用的RPC框架。Protobuf 本身虽然提供了RPC  的定...

25770
来自专栏北京马哥教育

IBM技术专家教你“懒惰”Linux管理员的10个关键技巧

作者:Vallard Benincosa, 来源: https://www.ibm.com/developerworks/cn/linux/l-10sysadt...

30850
来自专栏linux、Python学习

IBM技术专家教你“懒惰”Linux管理员的10个关键技巧

好的系统管理员区分在效率上。如果一位高效的系统管理员能在 10 分钟内完成一件他人需要 2 个小时才能完成的任务,那么他应该受到奖励(得到更多报酬),因为他为公...

10600
来自专栏腾讯移动品质中心TMQ的专栏

iOS 静态代码扫描之工具调研

为了进一步加强测试质量,同时探索测试左移在同步中的实践,iOS同步助手尝试接入静态代码扫描工具。希望通过不同的途径提前发现日常测试中难发现的问题。

1.5K10
来自专栏北京马哥教育

让“懒惰” Linux 运维工程师事半功倍的 10 个关键技巧!

好的Linux运维工程师区分在效率上。如果一位高效的Linux运维工程师能在 10 分钟内完成一件他人需要 2 个小时才能完成的任务,那么他应该受到奖励(得到更...

41060
来自专栏SDNLAB

从NETCONF/YANG看网络配置自动化

1 引子 NETCONF和YANG的目的是以可编程的方式实现网络配置的自动化,从而简化和加快网络设备和服务的部署,为网络运营商和企业用户节约成本。NETCONF...

50350
来自专栏子勰随笔

SDK设计心得之接口设计

2.1K90
来自专栏沈唁志

Windows 10文件系统错误-2147219196亲测有效的解决办法

说实话,Windows 10 的自动更新的确是存在一定风险,有可能将有bug的新补丁直接给推送了。所以还是建议大家,不要在微软一发布补丁就给更新上,可以尝试等待...

44120
来自专栏架构师之路

缓存,你真的用对了么?

缓存,是互联网分层架构中,非常重要的一个部分,通常用它来降低数据库压力,提升系统整体性能,缩短访问时间。

23720
来自专栏微服务生态

由多线程内存溢出产生的实战分析

一日凌晨,手机疯狂报警,短信以摧枯拉朽之势瞬间以百条的速度到达,我在睡梦中被惊醒,看到短信的部分内容如下:

14460

扫码关注云+社区

领取腾讯云代金券