原文:CPU阿甘
前言
上帝为你关闭了一扇门,就一定会为你打开一扇窗这句话来形容我最合适不过了。
我是CPU, 他们都叫我阿甘, 因为我和《阿甘正传》里的阿甘一样, 有点傻里傻气的。
上帝把我制造出来, 给我了一个很小的脑容量, 为数不多的寄存器能临时的记一点东西, 但是上帝给我打开了一扇特别的窗户, 那就是像阿甘一样,跑的飞快。
到底有多快呢? 我这么比喻一下吧, 我的工作都是以纳秒为单位的, 你们人间的一秒, 我可能已经做了1000,000,000 (10亿)次动作了。
相比而言, 内存比我慢100倍, 硬盘比我慢1000多万倍, 你说我快不快?
我是CPU, 他们都叫我阿甘, 因为我和《阿甘正传》里的阿甘一样, 有点傻里傻气的。
上帝把我制造出来, 给我了一个很小的脑容量, 为数不多的寄存器能临时的记一点东西, 但是上帝给我打开了一扇特别的窗户, 那就是像阿甘一样,跑的飞快。
到底有多快呢? 我这么比喻一下吧, 我的工作都是以纳秒为单位的, 你们人间的一秒, 我可能已经做了1000,000,000 (10亿)次动作了。
相比而言, 内存比我慢100倍, 硬盘比我慢1000多万倍, 你说我快不快?
启动
我住在一个机箱里,每天早上一阵电流把我叫醒, 还夹杂着嗡嗡的声音, 我知道我忠实的护卫电风扇又开始工作了, 我特别怕热, 又运行的飞快, 如果没有电风扇给我降温, 我很快就会生病, 生病的后果很严重, 那就是我的伙伴们像内存了,硬盘了。。全部都要罢工了, 没有我这个系统就会陷入的一片死寂。
我听说有些CPU的福利很好,竟然待在恒温恒湿,一尘不染的托管机房里,让我好生羡慕。
我的脑容量很小, 所以醒来后只想起了我的创造者告诉我的几件事情 :1. 你的工作就是运行指令2. 你不能保存指令, 你的指令全在内存里3. 你的第一条指令在内存的最顶端处0xFFFFFFF0
那还有什么可说的, 赶紧打电话给内存要指令,电话通过系统总线, 还得通过I/O桥电话局需要转接一下, 再通过存储总线接通 内存。
"哥们, 把这个地址处的指令给我说一下吧"
"你是谁?" 内存竟然把我忘了, 当然,他断了电和我一样,失忆了。
"我是阿甘啊, 我们经常聊天来着, 你忘了?"
内存磨磨唧唧半天才把数据发了过来(比我慢100倍啊), 这是一条跳转指令, 我立刻回忆起来了, 这是我的老朋友BIOS 等着我去运行他那一堆指令呢。
我给BIOS打电话: “老弟,今天干点啥?”
“阿甘,早上好 " BIOS从不失忆,把所有人都记得清清楚楚 “ 还不是老一套啊,无非做一下系统的自检, 看看内存,硬盘,显卡等这些老伙计们有没有问题, 有问题的话用小喇叭提示一下主人 ”
这些过程我已经轻车熟路了, 很快搞定, 像往常一样,没有问题, 我还把一个叫做中断向量表的东西给弄好了, 我知道一会而要用
这些东西都搞完了,BIOS果然告诉: "阿甘, int 0x19"
我赶紧去刚弄好的中断向量表中去查第19号, 顺藤摸瓜又找到对应0x19的一大堆指令。
执行吧, 这堆指令把将磁盘的第一扇区(磁盘最开始的512字节)运到内存的0X0000:0X7C00处,然后我就从此处接着执行。
我想起来了, 接下来有一大堆精巧的指令把迷迷糊糊的操作系统从硬盘中唤醒, 运输到内存中来。(此处实在是复杂, 略去10万字。。。。)
你看这就是为啥他们叫我阿甘, 我做事飞快,但非得别人告诉去哪里执行才行, 要不然我就只会坐在那里无所适从。
我听说有些CPU的福利很好,竟然待在恒温恒湿,一尘不染的托管机房里,让我好生羡慕。
我的脑容量很小, 所以醒来后只想起了我的创造者告诉我的几件事情 :1. 你的工作就是运行指令2. 你不能保存指令, 你的指令全在内存里3. 你的第一条指令在内存的最顶端处0xFFFFFFF0
那还有什么可说的, 赶紧打电话给内存要指令,电话通过系统总线, 还得通过I/O桥电话局需要转接一下, 再通过存储总线接通 内存。
"哥们, 把这个地址处的指令给我说一下吧"
"你是谁?" 内存竟然把我忘了, 当然,他断了电和我一样,失忆了。
"我是阿甘啊, 我们经常聊天来着, 你忘了?"
内存磨磨唧唧半天才把数据发了过来(比我慢100倍啊), 这是一条跳转指令, 我立刻回忆起来了, 这是我的老朋友BIOS 等着我去运行他那一堆指令呢。
我给BIOS打电话: “老弟,今天干点啥?”
“阿甘,早上好 " BIOS从不失忆,把所有人都记得清清楚楚 “ 还不是老一套啊,无非做一下系统的自检, 看看内存,硬盘,显卡等这些老伙计们有没有问题, 有问题的话用小喇叭提示一下主人 ”
这些过程我已经轻车熟路了, 很快搞定, 像往常一样,没有问题, 我还把一个叫做中断向量表的东西给弄好了, 我知道一会而要用
这些东西都搞完了,BIOS果然告诉: "阿甘, int 0x19"
我赶紧去刚弄好的中断向量表中去查第19号, 顺藤摸瓜又找到对应0x19的一大堆指令。
执行吧, 这堆指令把将磁盘的第一扇区(磁盘最开始的512字节)运到内存的0X0000:0X7C00处,然后我就从此处接着执行。
我想起来了, 接下来有一大堆精巧的指令把迷迷糊糊的操作系统从硬盘中唤醒, 运输到内存中来。(此处实在是复杂, 略去10万字。。。。)
你看这就是为啥他们叫我阿甘, 我做事飞快,但非得别人告诉去哪里执行才行, 要不然我就只会坐在那里无所适从。
运行
操作系统一旦进入内存,立刻就是老大, 所有人都得听他指挥。
我也发现我的周围出现了一个屋子:进程屋屋里堆着一大堆东西, 什么进程描述信息包裹了, 进程控制信息包裹了, 我都不太关心, 我只关心最最重要的两件东西:1. 我工作必备的寄存器, 就放在我面前的工作台上。2. 程序计数器, 我用它记住我要执行的下一条指令地址。
"阿甘, 别来无恙啊" , 操作系统对我还是挺不错的, 先给我打招呼。
"Linux老大, 今天有什么活啊", 我每次都表现的积极主动。
"来,把这个hello world 程序给运行了"
Hello world 程序还在硬盘上睡着呢, 得先把他也装载到内存里, 要不然我怎么执行啊。
于是我就拿起电话打给硬盘, 电话通过系统总线来到IO桥电话局, 再转接到IO总线,这才来到硬盘这里。
我在电话里请他把数据给我运过来, 然后我就无所事事的坐在那里等。
Linux 老大立刻就怒了 : 阿甘, 告诉你多少次了, 你小子怎么还在等硬盘给你发数据!
是的, 我忘了一件事,硬盘比我慢太多了, 我执行一条指令大概是1ns ,在用来读磁盘的16ms里, 我能潜在的执行1600多万条指令啊。
我感到深深的愧疚, 赶紧拿起电话打给硬盘 : 哥们, 按我们之前商量好的,用直接内存访问(DMA)啊, 你直接把数据装载到内存吧, 不用经过我了, 装载完成以后给我发个信号。
"这还差不多" Linux 老大心情好了些 “阿甘,数据还没来, 别闲着, 这有一个菲波那切数列数列, 来算一下吧”
"肥波纳妾数列? 这名字好古怪,老大, 其实你也知道, 我脑子小,懒得去理解那是啥意思, 你把进程屋切换下,把程序计数器设置好,指向下一条指令, 我一条条指令执行就得了“ 我挺没追求的。
"真是个阿甘啊! ”老大感慨到。
我所处的进程屋立刻发生了变化(当然,这也是我辅助Linux老大干的), 各种包裹的信息都变了, 尤其是寄存器和程序计数器。
于是我就开始计算这个什么纳妾数列 ,但是这个数列似乎无穷无尽, 哪个无脑子的程序员写了个无限循环吧。
正在这时, 我便收到了一个电话, 说是Helloworld的数据已经装载到内存了, 让我去处理。
我放下手中的活, 保存好现场, 就去处理那个Helloworld, 果然数据已经都好了, 那就切换过去运行吧。
其实老大并不知道, 任何人,只要你运行了相当多的数量的指令以后, 你都能悟到这些程序的秘密。 我CPU阿甘虽然傻傻的, 但也架不住执行这数以万万亿的指令给我的熏陶啊。
这个秘密就是:程序都是由顺序,分支,循环来组成的。 其实分支和循环在我看来都是跳转而已。
所以我的工作就是打电话问内存要一条指令, 执行这个指令, 如果是个跳转指令的话,我就问内存要跳转的目标地址的那一条指令, 继续执行, 生活就是这么简单。
奥对了, 当然也有复杂的, 就是函数调用, 我得和内存紧密配合才能完成。 这个咱下回再说。
我也发现我的周围出现了一个屋子:进程屋屋里堆着一大堆东西, 什么进程描述信息包裹了, 进程控制信息包裹了, 我都不太关心, 我只关心最最重要的两件东西:1. 我工作必备的寄存器, 就放在我面前的工作台上。2. 程序计数器, 我用它记住我要执行的下一条指令地址。
"阿甘, 别来无恙啊" , 操作系统对我还是挺不错的, 先给我打招呼。
"Linux老大, 今天有什么活啊", 我每次都表现的积极主动。
"来,把这个hello world 程序给运行了"
Hello world 程序还在硬盘上睡着呢, 得先把他也装载到内存里, 要不然我怎么执行啊。
于是我就拿起电话打给硬盘, 电话通过系统总线来到IO桥电话局, 再转接到IO总线,这才来到硬盘这里。
我在电话里请他把数据给我运过来, 然后我就无所事事的坐在那里等。
Linux 老大立刻就怒了 : 阿甘, 告诉你多少次了, 你小子怎么还在等硬盘给你发数据!
是的, 我忘了一件事,硬盘比我慢太多了, 我执行一条指令大概是1ns ,在用来读磁盘的16ms里, 我能潜在的执行1600多万条指令啊。
我感到深深的愧疚, 赶紧拿起电话打给硬盘 : 哥们, 按我们之前商量好的,用直接内存访问(DMA)啊, 你直接把数据装载到内存吧, 不用经过我了, 装载完成以后给我发个信号。
"这还差不多" Linux 老大心情好了些 “阿甘,数据还没来, 别闲着, 这有一个菲波那切数列数列, 来算一下吧”
"肥波纳妾数列? 这名字好古怪,老大, 其实你也知道, 我脑子小,懒得去理解那是啥意思, 你把进程屋切换下,把程序计数器设置好,指向下一条指令, 我一条条指令执行就得了“ 我挺没追求的。
"真是个阿甘啊! ”老大感慨到。
我所处的进程屋立刻发生了变化(当然,这也是我辅助Linux老大干的), 各种包裹的信息都变了, 尤其是寄存器和程序计数器。
于是我就开始计算这个什么纳妾数列 ,但是这个数列似乎无穷无尽, 哪个无脑子的程序员写了个无限循环吧。
正在这时, 我便收到了一个电话, 说是Helloworld的数据已经装载到内存了, 让我去处理。
我放下手中的活, 保存好现场, 就去处理那个Helloworld, 果然数据已经都好了, 那就切换过去运行吧。
其实老大并不知道, 任何人,只要你运行了相当多的数量的指令以后, 你都能悟到这些程序的秘密。 我CPU阿甘虽然傻傻的, 但也架不住执行这数以万万亿的指令给我的熏陶啊。
这个秘密就是:程序都是由顺序,分支,循环来组成的。 其实分支和循环在我看来都是跳转而已。
所以我的工作就是打电话问内存要一条指令, 执行这个指令, 如果是个跳转指令的话,我就问内存要跳转的目标地址的那一条指令, 继续执行, 生活就是这么简单。
奥对了, 当然也有复杂的, 就是函数调用, 我得和内存紧密配合才能完成。 这个咱下回再说。
新装备:缓存
提到内存, 这真是我的好哥们, 没有他,我几乎什么事儿都干不成, 更重要的是他比硬盘快的多, 读取一次数据, 只需要 100 纳秒左右。 这样我们俩说起话来就轻松多了。
每次他都说: "阿甘, 幸亏有你给我聊天, 要不然我肯定被活活的闷死不可, 那个硬盘说话是在太慢了"
"它为啥那么慢?" 我每次都问
"硬盘是个机械是的玩意, 一个磁头在一碟高速旋转的磁片上挪来挪去,光定位就慢死了"
"那主人为什么要用硬盘?"
"人家虽然慢, 但是不怕停电, 哪像你和我,一停电全部都失去记忆了。"
确实是, 人不能把好事都占全了啊。
我的指令中有些完全用我的寄存器就能完成, 但是有很多都需要读写内存的数据, 再加上所有的指令都在内存中存着, 虽然它只比我慢个100倍, 但指令多了我还是有点受不了。
我给内存说:"哥们, 你能不能再快点!"
内存说: 拜托, 这已经是我的极限了, 阿甘, 你自己再想想办法吧 ! 我给你说啊, 我留意了你最近访问的指令和数据, 我发现了个规律“
"啥规律?"
"比如说吧, 你访问了我一个内存位置以后过不多久还会多次访问, 还有,一个内存位置被访问了, 附近的位置很快也会访问到"(码农翻身注: 这其实叫程序的局部性原理)
我还以为是啥规律, 其实我早就注意到了。
"这有啥用啊?”
"既然你经常访问同一块区域的东西, 你想想如果把这些东西缓存在你那里会怎么样.... "
我一想有道理啊! 加个缓存试试!
从此以后,我每次读写指令和数据, 都问缓存要, 缓存没有才给内存打电话。
果然, 由于局部性原理的存在, 我发现的确是快了不少啊。
当然也有缺点, 那就是Linux老大在做程序切换的时候, 缓存就会失效,因为两个程序之间没什么联系,局部性原理不起作用, 所以需要重建缓存。
自我提升:流水线
每次他都说: "阿甘, 幸亏有你给我聊天, 要不然我肯定被活活的闷死不可, 那个硬盘说话是在太慢了"
"它为啥那么慢?" 我每次都问
"硬盘是个机械是的玩意, 一个磁头在一碟高速旋转的磁片上挪来挪去,光定位就慢死了"
"那主人为什么要用硬盘?"
"人家虽然慢, 但是不怕停电, 哪像你和我,一停电全部都失去记忆了。"
确实是, 人不能把好事都占全了啊。
我的指令中有些完全用我的寄存器就能完成, 但是有很多都需要读写内存的数据, 再加上所有的指令都在内存中存着, 虽然它只比我慢个100倍, 但指令多了我还是有点受不了。
我给内存说:"哥们, 你能不能再快点!"
内存说: 拜托, 这已经是我的极限了, 阿甘, 你自己再想想办法吧 ! 我给你说啊, 我留意了你最近访问的指令和数据, 我发现了个规律“
"啥规律?"
"比如说吧, 你访问了我一个内存位置以后过不多久还会多次访问, 还有,一个内存位置被访问了, 附近的位置很快也会访问到"(码农翻身注: 这其实叫程序的局部性原理)
我还以为是啥规律, 其实我早就注意到了。
"这有啥用啊?”
"既然你经常访问同一块区域的东西, 你想想如果把这些东西缓存在你那里会怎么样.... "
我一想有道理啊! 加个缓存试试!
从此以后,我每次读写指令和数据, 都问缓存要, 缓存没有才给内存打电话。
果然, 由于局部性原理的存在, 我发现的确是快了不少啊。
当然也有缺点, 那就是Linux老大在做程序切换的时候, 缓存就会失效,因为两个程序之间没什么联系,局部性原理不起作用, 所以需要重建缓存。
自我提升:流水线
缓存让我的工作更有效率, 得到了Linux老大的表扬:"阿甘, 我看你很聪明嘛, 都会用缓存了"
"我哪有那么聪明,都是内存的点子。老大,不过我学会了一个重要的东西 :当你改变不了别人的话,抱怨也没用, 还是先改变一下自己吧"
"挺有哲理的吗, 希望你明天重启后还能想起来" Linux老大笑话我。
"我最近又发现了一个问题, 正苦恼着呢, 你看我有四只手, 第一只手负责打电话问内存要指令, 第二只手翻译指令, 第三只手真正执行, 第四只手有时候还得把结果写回内存。 问题是, 我发现经常只有一只手在忙活, 其他都在闲着, 你看第一只手取指令, 其他手只能等着。 第二只手翻译指令的时候,其他三只也得等“
"看来以后我们不能叫你阿甘了, 你已经开始思考了" Linux老大笑了
“这问题好解决, 给你举个例子,你听说过洗车没有? 和你差不多, 也是先喷水, 再打洗洁剂, 再擦洗, 最后烘干, 但人家的工作方式和你不一样,人家是流水线作业, 你想想, 一辆车在烘干的时候, 后边是不是还有三辆车,分别在喷水, 打清洁剂 和擦洗 , 每个步骤都不会空闲。 ”
"这么简单的道理我怎么都没有想到呢? 我也可以搞个流水线啊, 这样每只手都利用起来了"
别人都说我们高科技, 但其实原理都蕴含在生活之中啊。
有了缓存和流水线的帮助, 让我的工作大大的加快了,大家都对我刮目相看。 他们想给我起个新名字:超人 , 不过我还是更喜欢 他们叫我“阿甘”, 多亲切。
"我哪有那么聪明,都是内存的点子。老大,不过我学会了一个重要的东西 :当你改变不了别人的话,抱怨也没用, 还是先改变一下自己吧"
"挺有哲理的吗, 希望你明天重启后还能想起来" Linux老大笑话我。
"我最近又发现了一个问题, 正苦恼着呢, 你看我有四只手, 第一只手负责打电话问内存要指令, 第二只手翻译指令, 第三只手真正执行, 第四只手有时候还得把结果写回内存。 问题是, 我发现经常只有一只手在忙活, 其他都在闲着, 你看第一只手取指令, 其他手只能等着。 第二只手翻译指令的时候,其他三只也得等“
"看来以后我们不能叫你阿甘了, 你已经开始思考了" Linux老大笑了
“这问题好解决, 给你举个例子,你听说过洗车没有? 和你差不多, 也是先喷水, 再打洗洁剂, 再擦洗, 最后烘干, 但人家的工作方式和你不一样,人家是流水线作业, 你想想, 一辆车在烘干的时候, 后边是不是还有三辆车,分别在喷水, 打清洁剂 和擦洗 , 每个步骤都不会空闲。 ”
"这么简单的道理我怎么都没有想到呢? 我也可以搞个流水线啊, 这样每只手都利用起来了"
别人都说我们高科技, 但其实原理都蕴含在生活之中啊。
有了缓存和流水线的帮助, 让我的工作大大的加快了,大家都对我刮目相看。 他们想给我起个新名字:超人 , 不过我还是更喜欢 他们叫我“阿甘”, 多亲切。
尾声
我一丝不苟,兢兢业业的运行指令, 时不时和伙伴们聊天, 很快一天就过去了, 又到了晚上,我知道关机的时刻到了, 赶紧挨个给他们道别。
很快那些让我兴奋的电流消失了,风扇的嗡嗡声也没有了, 我再也无法打出电话,整个世界沉寂了。
明天将会是新的一天。
备注: 本文内容主要来自于《深入理解计算机系统》, 这本书非常棒,值得每个程序员仔细研读。公众号:码农翻身“码农翻身”公众号由工作15年的前IBM架构师创建,分享好玩,有趣的编程知识。
很快那些让我兴奋的电流消失了,风扇的嗡嗡声也没有了, 我再也无法打出电话,整个世界沉寂了。
明天将会是新的一天。
备注: 本文内容主要来自于《深入理解计算机系统》, 这本书非常棒,值得每个程序员仔细研读。公众号:码农翻身“码农翻身”公众号由工作15年的前IBM架构师创建,分享好玩,有趣的编程知识。