关于《深入理解计算机系统》

“这本书的中译名为“深入理解计算机系统”,我非常,十分,以及百分之一百二十地不满意。我这么说的原因在于这个译法完全扭曲了书的本意。如果直译原书名,应该是类似于“以程序员的视角理解计算机系统”,何来“深入”二字。可能在国内编辑看来,这是讲系统的,用C和汇编语言的,因此很“深入”,但我认为这只能说明国内技术氛围的浅薄。因为事实上,这是一本入门级别的书,这本书其实并不“深入”,它谈论的内容还是相对比较浅的。但“浅”不代表“浅薄”,写一本面向初学者的好书往往是非常困难的,因此无论是SICP还是CSAPP,它的作者都是顶尖学府的教授,结合多年教学经验而写出来的。

CMU把这本书作为“Introduction to Computer System”课程的教材,是面向计算机专业低年级学生的“计算机系统介绍(导论)”,可能这些学生只是刚刚了解如何使用一门高级语言——如Java进行编程,对于计算机系统的工作方式等话题可谓一点都没有接触过,而CSAPP对读者的背景也只要求是“一些编程经验”而已。这本书的话题覆盖面很广,从计算机的基本组成,二进制数据表示方式,到机器级别的指令,CPU工作方式,存储结构和优化,操作系统的虚拟内存管理,程序运行方式,I/O,网络、到(较底层)程序性能优化和并行程序开发等等。所以,它其实覆盖了“计算机组成原理”,“操作系统”等许多课程的内容,其中的许多话题都能再次展开,继续深入,都能再变成一本,甚至N本经典。事实上,在高年级的计算机专业课程设置中,都会有更加纵向的内容出现。”                                                                                     ——摘自Jeffrey Zhao博文

老赵的这一番话,值得深思,这本书用怎么说呢,并不是深入,而是涉及的知识比较广,但又都是广大程序猿不得不知道的知识,下面我们就来慢慢品尝这本书吧。言归正传,接下来,享读《Computer Systems: A Programmer’s Perspective》的中hello world程序都干了些啥。

1.信息在计算机的中表示

当我们输入以下程序,编译运行,计算机从屏幕输出hello, world。整个过程计算机都怎么运作的呢?

#include <stdio.h>

int main()

{

printf("hello, world\n");

}

我们知道,信息在计算机中都是用0或1表示的。计算机通过这些位信息以及上下文来解读这些0/1。也即:计算机中的信息=位+上下文。

我们输入的hello程序就是由0、1组成的序列,将这些位8位组织成一个字节,每个字节用来表示一个文本字符。ASCII码给出了一种字符与数字的一一对应关系。

hello, world程序以字节方式存放于文件中,如下图所示。其每个字符对应一个数字,具体可参考ASCII码表。

图1 Hello world程序的ASCII码表示

2.将程序翻译成机器可读的格式

因为我们输入的hello, world程序是人可读的,机器并不能直接识别它们。我们需要把这些文字翻译成机器可执行的二进制文件。这一部分的工作是由编译系统完成的。编译系统由预处理器、编译器、汇编器、连接器四部分组成。以hello, world程序为例,各部分共同完成将源文件编译成二进制可执行文件。各个部分完成的具体工作如下:

l 预处理器:根据以#开头的命令,修改源程序。如根据#include <stdio.h>行,预处理器读取系统头文件stdio.h中的内容,代替此行内容。源程序经过预处理后,得到另一个c程序,此程序通常以.i为后缀保存。

l 编译器:将预处理后的.i文件转换成汇编程序。编译器将不同的高级语言(如c语言,C++语言)转换成严格一致的汇编语言格式进行输出。汇编语言以标准的文本格式确切的描述每机器语言指令。编译器得到的文件通常以.s为后缀保存。

l 汇编器:将汇编语言(.s文件)翻译成机器语言指令,并将这些指令打包成一种可定位目标程序格式。汇编后得到的文件即为二进制文件,通常以.o为后缀。

l 链接器:hello, world程序中调用过printf函数,它是一个c标准库里的函数。Printf函数存放在一个名为printf.o的单独预编译的文件中。而这个文件必须以适当的方式并入到我们的程序中,这个工作由链接器完成。将外部的.o文件并入后,得到一个完整的hello, world可执行文件。可执行文件加载到存储器后,由系统复制执行。

图2 编译系统

在linux系统上,输入编译命令行:

Viidiot>gcc hello.c -o hello

将执行上图所示的四个步骤,得到可执行二进制文件hello。

3.处理器读取并解释存储在存储器中的指令

Shell:命令行解释器,为用户提供了一只与系统打交道的方式。它等待用户的输入,当用户输入一行命令后,shell先判断它是不是一个shell内置命令,如果不是,shell会假定用户输入为一个可执行文件的名字,从而去加载并执行该文件。因此,当我们通过编译系统将源文件编译成可执行二进制文件后,在shell中输入我们得到的可执行二进制文件名,shell将其从磁盘中加载到存储器(注:我们的可执行文件是存放在磁盘上的),并通过处理器进行解释执行,得到最终的结果,输出到终端(显示器)上进行显示。自此,我们的hello, world程序完成了其生命周期。

4.计算机系统硬件结构

为了弄清楚hello, world运行时,系统究竟发生了什么,我们先来了解下一个典型的计算机硬件结构。

图3 典型的计算机硬件构成

【CPU:中央处理器   ALU:算术/逻辑运算单元  PC:程序计数器  USB:统一串行接口】

下面简单说一下各个部件在系统中所起的作用。

总线:在各个部件之间传输数据。现在的总线宽度一般为32位或者64位,即一次传输的数据为4字节或者8字节。

I/O设备:IO设备是系统与外界通信的通道,如鼠标,键盘,显示器都是典型的IO设备。

主存储器:简称主存,是处理器执行程序时用于临时存放程序及其数据。主存由一组动态随机存储器芯片组成。

处理器:解释执行存储在主存中的指令。其内部包含一个双字节程序计数器(PC),任何时候PC中都存放着接下来要执行的机器指令在主存中的地址。

处理器的操作主要是围绕PC、ALU、主存来进行运作的。处理器首先从PC所指向的主存存储单元读取指令,解释指令中的位,执行该指令指示的简单操作,然后更新PC寄存器,使其指向下一条要执行的指令。CPU会执行的操作有:

加载:把一个字节或一个字从主存复制到寄存器,覆盖掉寄存器中原来的值。

存储:把一个字节或一个从寄存器复制到主存,并覆盖主存中原来的值。

操作:把两个寄存器的内容复制到ALU,ALU对两个字做算术运算后存回其中的一个寄存器,该寄存器中原来的值会被覆盖。

跳转:从cpu执行的指令抽取一个字的内容存入PC,覆盖掉原来的值,从而改变下一条要执行的指令,达到跳转的目的。

在了解了一些基本的硬件结构,以及各个部分的作用后,我们再来看看之前的hello, world程序的运行过程。

图4 加载可执行文件到主存的过程

在linux系统下,我们在shell中敲入以下命令

Viidiot>./hello

由于shell没有内置hello命令,因此shell将我们输入的hello视为一个可执行文件,从而通过执行一系列机器指令,将可执行文件hello从磁盘复制到主存,如图4所示。

注意,如果通过DMA方式加载程序,则不需要通过CPU,而是将hello可执行文件直接从磁盘复制到主存,示意图如图5。

图5 DMA方式加载程序到主存

可执行程序加载到主存后,cpu就执行hello程序的机器指令,而这些指令完成的工作便是将”hello,world\n”这几个字符从主存中复制寄存器文件中(register file),再将其从寄存寄文件中复制到显示设备上进行显示。过程示意图如图6所示。

图6  cpu执行指令,将 “hello,world\n”从内存复制到显示设备

至此,hello,world程序的执行过程已经完成。

题外话:

从上面的程序实例我们可以看到,程序花费了大量的时间将数据从一个部件复制到另外一个部件。程序加载时,将hello程序的机器指令从磁盘复制到主存,程序运行时,又将其从主存复制到cpu,最后又从cpu复制到外部显示器。将根据机械原理,大容量的存储设备速度比小容量存储设备慢,快速设备的造价比慢速设备的造价高。对于计算机硬件系统,CPU的速度远高于主存的速度,而主存的速度远高于磁盘,不同部件的速度严重不对等,从而快的设备的性能没能得到充分发挥。为解决各类设备速度不匹配的问题,引入了高速缓存设备来缓解速度匹配问题。如图7所示,为加入了高速缓存后的系统部分结构。

图7 高速缓存存储器

现代计算机为提高系统性能,一般都加入了多级缓存结构。高速缓存采样的是静态随机存储器硬件(SRAM)技术,速度快于主存(采样动态随机存储器技术)。如图8是存储器结构金字塔,越往上速度越快,造价也更昂贵。

图8 存储器金字塔

作者:Viidiot   微信公众号:linux-code


hello world是怎样运行的?的更多相关文章

  1. ASP.NET Aries 入门开发教程1:框架下载与运行

    背景: 鉴于框架的使用者越来越多,文档太少,不少用户反映框架的入门门槛太高. 好吧,再辛苦下,抽时间写教程吧! 步骤1:下载框架源码 开源地址:https://github.com/cyq1162/A ...

  2. 在传统.NET Framework 上运行ASP.NET Core项目

    新的项目我们想用ASP.NET Core来开发,但是苦于我们历史的遗产很多,比如<使用 JavaScriptService 在.NET Core 里实现DES加密算法>,我们要估计等到.N ...

  3. Sublime Text3配置在可交互环境下运行python快捷键

    安装插件 在Sublime Text3下面写代码感觉很不错,但是写Python的时候遇到了一些问题. 用Sublime Text3打开python文件,或者在Sublime Text3下写好pytho ...

  4. hadoop 2.7.3本地环境运行官方wordcount-基于HDFS

    接上篇<hadoop 2.7.3本地环境运行官方wordcount>.继续在本地模式下测试,本次使用hdfs. 2 本地模式使用fs计数wodcount 上面是直接使用的是linux的文件 ...

  5. hadoop 2.7.3本地环境运行官方wordcount

    hadoop 2.7.3本地环境运行官方wordcount 基本环境: 系统:win7 虚机环境:virtualBox 虚机:centos 7 hadoop版本:2.7.3 本次先以独立模式(本地模式 ...

  6. Docker笔记一:基于Docker容器构建并运行 nginx + php + mysql ( mariadb ) 服务环境

    首先为什么要自己编写Dockerfile来构建 nginx.php.mariadb这三个镜像呢?一是希望更深入了解Dockerfile的使用,也就能初步了解docker镜像是如何被构建的:二是希望将来 ...

  7. Linux scp 设置nohup后台运行

    Linux scp 设置nohup后台运行 1.正常执行scp命令 2.输入ctrl + z 暂停任务 3.bg将其放入后台 4.disown -h 将这个作业忽略HUP信号 5.测试会话中断,任务继 ...

  8. 在docker中运行ASP.NET Core Web API应用程序(附AWS Windows Server 2016 widt Container实战案例)

    环境准备 1.亚马逊EC2 Windows Server 2016 with Container 2.Visual Studio 2015 Enterprise(Profresianal要装Updat ...

  9. Android数据存储之Android 6.0运行时权限下文件存储的思考

    前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...

  10. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

随机推荐

  1. Linux配置系统

    配置架构: 三元素: 配置文件, 环境变量, 命令行选项 三级别: 系统级,用户级,程序级 应用: 调用时可能发生变化的配置信息,使用命令行选项:改动很少但确实应该由各个用户自己控制的配置信息,使用用 ...

  2. Druid数据库连接池两种简单使用方式

    阿里巴巴推出的国产数据库连接池,据网上测试对比,比目前的DBCP或C3P0数据库连接池性能更好 简单使用介绍 Druid与其他数据库连接池使用方法基本一样(与DBCP非常相似),将数据库的连接信息全部 ...

  3. 安装Sublime Text 3插件

    按 Ctrl+` 或者如下图调出Console 粘贴以下代码到底部命令行并回车: import urllib.request,os; pf = 'Package Control.sublime-pac ...

  4. AS 学习笔记 加载数据

    AS2 加载本地(外部)数据.swf .png .jpg 等资源使用loadMovie() 加载库里面的mc 用 attachMovie AS3 加载本地(外部)数据 用 Loader 类来完成这个操 ...

  5. Import data from SQLServer with Sqoop

    author: luciuz date: 2013/11/15 -------------------------------------------------------------------- ...

  6. Colored Sticks (字典树哈希+并查集+欧拉路)

    Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 27704   Accepted: 7336 Description You ...

  7. ThinkPadTablet如何恢复出厂状态

    ThinkPad Tablet恢复出厂操作教程: 第一步:开机看到“LENOVO”图标后不停按机器侧面音量增大键,直到出现“Booting recovery kernel image”字样. 第二步: ...

  8. SQL Server查询性能优化——堆表、碎片与索引(二)

    本文是对 SQL Server查询性能优化——堆表.碎片与索引(一)的一些总结.  第一:先对 SQL Server查询性能优化——堆表.碎片与索引(一)中的例一的SET STATISTICS IO之 ...

  9. hbase单机环境的搭建和完全分布式Hbase集群安装配置

    HBase 是一个开源的非关系(NoSQL)的可伸缩性分布式数据库.它是面向列的,并适合于存储超大型松散数据.HBase适合于实时,随机对Big数据进行读写操作的业务环境. @hbase单机环境的搭建 ...

  10. [MarsZ]程序猿谈大学之工作三年半的程序猿给大学童鞋的一些注释

    我本不是个喜欢写文章的人,更甭提写这种基本没技术含量的文章了.但是今天上班的时候,不经意浏览了下学校的QQ群,突然很想把自己的经验经历分享给还在大学里的同学,希望能让某些对前途职业迷茫的童鞋有所帮助. ...