这些系统一个比一个复杂,可是请记住一句话:全部的基本思想都是也必须是朴素的,简单的!
或许,非常多人看到这里就觉得有点不屑一顾,毕竟他们觉得自己是技术狂人,觉得仅仅有摆弄复杂的东西才干证明自己的学识和技术,觉得上世纪70年代的被UNIX v6是一个过时的系统。里面的内容早就被岁月无情地抛弃了,但其实,假设你真的看了那个时代的UNIX源代码,或者读了莱昂氏的神书,而且细细琢磨之后,你会发现,那些朴素的观念一点也只是时,我们现在的非常多技术所依托的思想早在1975年的时候就已经被朴素地实现了。
三岁看老,无视历史就是轻蔑未来。
假设你想知道下一步我们要做什么。听别人讲是无用的,你必须亲自翻开历史。正如给你一条曲线的一部分。问你该曲线的下一步走势,你肯定能够猜个八九不离十。由于不论什么事物都是循着历史前进的,这就是读史使人明智。
前些日子和朋友一起吃饭。请客的是位芯片专家,可是对除芯片以外的不论什么事物都是不屑一顾。好一个中国传统的所谓术业有专攻。就好像世界上除了芯片是高科技之外,其它的都是小儿科。好一个排他!
可是你有没有通过这件事想到些什么,这位朋友是典型的中国式学究,所谓的术业有专攻的学究。正是这样的所谓的专攻,导致我们中国其实从来没有引领过一个时代。我们从早的说,农业革命发力于美索不达米亚以及尼罗河中下游,青铜时代是西亚和东欧游牧民族引领的,民主观念来自于希腊,帝国主义来自于罗马,工业革命来自于西欧。电力革命来自西欧。计算机革命来自美国,关于最后这一点我会具体说,以上这些我并没有提到文艺复兴,那是我有益的,由于假设我提到了文艺复兴。非常多人就会说,我们中国也有非常多这类事情,比方周昭共和。秦王扫六合。汉武大帝。光武中兴,贞观之治。...康乾盛世。可是你要知道,这些和文艺复兴一样。都是局域性事件。无论怎样,我们现在住着楼房。玩手机,玩电脑。开汽车。坐高铁,全部这些都是舶来品,没有一样是我们自己的。原因就在于我们的思维不够发散。我们做软件就是做软件。不知道一些思想还能够用于硬件。我们学OO学得非常精通。精通了C++,Java,却不知道OO来自AI...知道列维飞行却不知道它和计算机内存訪问模型的关联...
说了这么多看似无用的。其实是想说。弄点别的吧。尽管我们都是搞IT的。
非常多编程高手可能真的不屑于1975年的UNIX源代码。那就是历史,这位高手知道怎么设计类。知道怎么实现一个排序算法。可是也仅仅如此。说究竟,他仅仅是一个高价的雇佣兵,永远都成不了将军。而且随时都可能阵亡。我写这个系列的文章,就是想说明一点,用历史的眼光看操作系统以及不论什么技术的发展,你会得到很多其它,往窄的说,UNIX就是一座宝库,凡是你在现代软件中能找到的思想,在UNIX中都是它的影子。
在正式開始之前,简单的说一下背景。我们现在所面对的计算机早就不是40年前的计算机了。由于须要产业化和减少门槛,整个计算机产业和通讯产业经历了多次整合。终于我们把软件和硬件严格区分开来。而且在软件和硬件的各个组成部分之间也严格划分了界限,这样的结果就是有利于社会化分工,人们走上了术业有专攻的专业化道路(其实非常多思想家从古希腊梭伦时代開始就開始抨击专业化了)。可是其缺点也是显而易见的。那就是“对于geek而言。现代计算机已经不好玩了”。
现代计算机已经不好玩了
看了Linus的自传,认同一点。现在的计算机已经不适合玩了,主要原因是已经不好玩了。Linus始终觉得技术为娱乐而生!值得注意的是,Linus的自传《Just for fun》并非要表达“计算机已经不好玩”这样的观点。可是Linus觉得,现在的计算机“和你的汽车一样复杂”,已经不适合让你随性折腾了。
其实,由于计算机已经不再好玩,我们也就无法或者非常难就计算机本身再创造所谓的“时代”!
现在搞计算机已经沦为了一种职业,一种谋生的手段。其内容也随之沦为了套路和规则!要想创造一个时代。你必须不能术业有专攻,你必须是全才。
时代是玩出来的,我以为!
当时的那帮人是无心为之的,之后当全部的玩法标准化时。利益便主宰了一切。能玩得转的东西必须是简单的,太复杂的东西在艺术上没有美感。在project学上你必须花费巨大的精力去进行复杂性管理,因此本质的东西便被隐藏在复杂性之下了,你非常难去挖掘它,赞赏它。最近读了几本书。颇有感受。
太复杂的东西,能够向不懂的人大肆炫耀。但其实。听的人根本不知道你在说什么。你仅仅是自说自话。孤芳自赏罢了。你可曾想过,为何大师都是扎堆出现的。古希腊的哲学家,中国先秦的诸子,文艺复兴时期的画家。20世纪初的物理学家。20世纪50-60年代的计算机天才,20世纪70年代的黑客...
计算机产业也是从全民折腾时代開始的,这就和希腊的梭伦改革一样。可是和希腊的伯里克利终结了一个时代一样。产业化。专业化也终结了计算机的嬉皮时代,现现在,仅仅有Richard Stallman。Eric S Raymond他们还在尽力延续那个geek的时代。而其实,现在的专业化让非常多准geek面对复杂的计算心有余而力不足。
那么,这个geek时代是怎么被终结的呢?我从软件和硬件相遇的地方说起。
硬件和软件相遇的地方
最初设计的机器并非想让每一个人都能够操控它的,它是隶属于精英阶层的。可是假设有人发现了这些机器中蕴藏的巨大的商机,他便会推动一种全民化运动,全民化运动发展到一定程度,技术已经足够复杂,就会出现专业化,于是这样的技术便逐渐远离了大众,再次被精英所垄断。正如它最初时那样。
对于计算机技术而言,我把前一个精英时代的技术成为硬件,我把后一个精英时代的技术称为软件,现在在硬件领域,拥有硅晶体技术。Verilog。HDL等。在软件领域。有JAVA。Python,PHP。OO。设计模式。敏捷开发等术语。专业性让全部这些东西都具有了排他的性质,而创造计算机时代的地方。正是软件和硬件相遇的地方,那就是汇编语言向C语言进化的地方。
要知道。假设你不懂机器的特性,你是用不好汇编语言的。假设你不懂机器的特性。你也不可能用C写出最高效的代码,反过来,假设你仅仅懂C语言,你也不可能将机器的能力发挥的淋漓尽致。汇编和C。这就是软件和硬件相遇的地方。时代就是它们开创的,历史就是它们写就的。
汇编语言编程让人循着机器指令走,程序猿非常难构建自己的高层逻辑。由于你要花费大量的精力在指令本身上,C语言出现后。人们的逻辑思维被解放了,你能够写诸如a=b+c这类语句了,而不必“先将马上数放入一个寄存器,再将马上数....两个寄存器的值相加或者一个寄存器和一个马上数直接相加,结果存在...”。C语言的最大共享在于攻克了“寻址问题”。这就意味着它攻克了全部的问题,由于计算机编程能够归为寻址的艺术,C将全部的寻址问题归结为一个概念,那就是指针!要知道,现代存储式计算机的执行,唯一的问题就是寻址问题,无论是数据还是指令,都存在内存中,你必须有办法能够在正确的地方找到指令或者数据。C指针屏蔽了全部的寻址细节。让轻松构建应用逻辑成了可能,这些应用逻辑包含复杂的条件语句。循环语句,goto语句,甚至缓冲区溢出。
硬件和软件的关系就是怎么做和做什么的关系,编程人员告诉硬件做什么之后就能够放心做别的事了。由于他相信硬件知道怎么做。这个接口就是C语言,而硬件的内部电路逻辑则实现了“怎么做”的逻辑。
水不知冰有多冷,冰不知水的多情。同一个东西。一旦被隔离。那就是隔行如隔山。本来硬件和软件是一家的,可现在变成了排他的两个行业,就算在软件行业内部,还常常有各种排他性的隔离,诸如什么“搞底层的”,“搞协议栈的”,“写类的”,...软硬通吃的全栈程序猿现在被人和酷(苦)逼联系在了一起。
可是在30-40年前。计算机时代就是这帮全栈程序猿开创的。在软件和硬件相遇的地方,那帮人同一时候属于硬件精英和软件精英,实际上他们引领的是一种全民玩转计算机的嘻哈时代,这个时代被20世纪70-80年代的黑客们所延续,众所周知的业界名人差点儿都出自那个由UNIX开启被黑客精神延续的时代。比方乔布斯的Apple,比尔.盖茨的Microsoft,理查德.斯托曼的GNU。比尔.乔伊的BSD。IBM PC,Intel IA32,...不胜枚举。这是一个简单纯真的时代。一个精简浓缩的年代。
PC技术与UNIX技术
PC技术使得计算机小型化。进而出现了微型化的趋势,随着工艺越来越先进,硬件越来越小,越来越廉价,巨大的商机促进了PC技术的发展。可是软件这方面却没有实时跟进。多用户多任务分时系统当时最风靡的就是UNIX。然而UNIX却受制于各种非技术因素的控制,正由于如此,才让微软,苹果等公司占了先机,它们两家你追我赶。一直到今天。导致这个结果的还有一个原因是UNIX从来都不属于草根(正由于如此才有了GNU)。而无论是苹果还是微软,都和一个叫“家酿俱乐部”的草根组织有关。大家在一个相对平和的环境中展示自己的机器和技术。那个时代是黑客的时代。能够说。UNIX并没有赶上PC时代的潮流,可是这就是UNIX。正如启蒙思想家本人不參加法国大革命一样。UNIX作为一位思想先驱,它的一些古老的观念。甚至Windows 8系统还在使用。
SVR4 VM的设计概念, 能够说是颠覆了传统对记忆体的理解;文件抽象使得IO接口变得简单;基于页面交换和按需调页实现的虚拟内存的思想影响了差点儿全部的操作系统设计;分级存储思想更绝妙,在CPU内部。CPU缓存是内存的Cache,在VM里面,物理内存是虚拟内存的Cache,在MMU,物理内存是磁盘或者网络的Cache...。最重要的还是UNIX进程模型(线程模型和进程组模型都是进程模型的扩展),它的重要性我真的不知道该怎么才干说得清。
不得不提到的是Intel和微软以及PC技术这三者的关系,可是这个话题过大,也仅仅能在此提示一下,总之,PC技术造就了两大帝国,而Intel和微软配合太默契。以至于成了一个好像罗马帝国那样的存在...
Mac OS X技术
UNIX成功的观念是,它从来不关注实现细节,由于细节会将你拉离目标。
UNIX仅仅提供基本理念,因此。无论是AIX,Solaris,Mach,xxBSD。它们的实现绝对截然不同,可是都叫做UNIX。假设微软愿意,Windows NT也能够称为UNIX,由于NT系统在70%的程度上实现了UNIX的基本理念。
在UNIX之外,有还有一条演进道路,那就是复杂性演化。它是严格遵循硬件的最新特性,软件迎合硬件。硬件惯坏软件,大家彼此阿谀奉承,实际上大家都忘了,其实原本大家都是一家。有些时候,仅仅为了一些单一的商业利益,就会把一些复杂但不普适的机制固化在硬件中,这一点的反例就是RISC架构。它就是UNIX在硬件领域的直接体现。
复杂性演化举例
数据的地址依照其类型的长度倍数自然对齐是一个不成文的编程约定。可是为何作如此的约定呢?难道不正确齐就不行吗?在某些架构的处理器上。真的就是不行,比方非常多的RISC处理器。然而在CISC架构的处理器,比方Intel/AMD x86架构处理器上,为了编程的方便,核心能够替你完毕这样的费力的操作。
这一切的根源在哪里?
在对整个事情分析之前,必须要明确的是,现代微处理器是超大规模集成电路的结晶,芯片是雕刻在硅这样的半导体上的。工艺极其考究,因此布线的简单就是一切的根本,在硅晶体上雕刻电路是多么的令人崇拜啊(还记得我们学过的《核舟记》吗)。硅晶体雕刻不像高级语言编程,它甚至不同意你将事情搞得太复杂(主要是晶体的布线难度)。因此非常多事情就要规定死,比方数据的自然对齐。完美的处理器架构仅仅须要实现一个完毕随意操作的最小指令集就可以,架构简单。能够将很多其它的硅晶体的空间用于实现高效的流水线而不是复杂的指令(某个复杂的指令往往和其它复杂指令拥有公共部分。这就造成了空间的浪费),这样的处理器叫做RISC处理器。以上这个事实是人们在早期集成电路技术开启这个新时代的伊始,走了非常多弯路才总结出来的,仅仅可惜,Intel就是那个最先吃螃蟹的人,随后它获得了巨大的成功,兼容它的指令集将AMD也拉下了水。
我们知道,抛开微处理器内部必须实现的运算逻辑,其与外部的接口就是寻址和IO。
Intel在最初实现16位微处理器的时候,恨不得为每一个我们能想到的寻址逻辑都实现一条硬件指令。其实它也是这么努力做的。翻开不论什么一本汇编语言的书,首先映入眼帘的就是大量的寻址指令,假设你对着Intel的手冊观摩。你会发现非常多寄存器都不是作为操作数存在的。而是内置于指令本身!
因此mov eax 1和mov ebx 1可能就是两条全然不同的指令,而不仅仅是操作数的不同,就这样,复杂指令的实现占领了大量的芯片面积,由于单独指令完毕的事务依旧可切割,且长度不一,Intel便非常难实现高效的长流水线。机器指令就是硬件和软件相遇的地方。是软件请求到硬件落实的唯一接口,为了兼容以前的软件,接口是不能随意更改的,可是当Intel意识到指令必须是足够简化,功能足够单一以便实现长流水线时,它上面的应用程序已经遍地开花了。
于是Intel和AMD的策略就是改动指令的实现,取指令之后。将单条的复杂指令切割为多条简单指令,即使用了万变不离其衷的神喻-加入一个中间层!
于是,Intel的指令其实终于也是由简单操作实现的,这些操作称为微操作。实现一条指令的微操作集合称为微程序。全部的微程序称为微码。
于是乎,x86架构实际上仅仅是在接口是CISC体系架构,其内核已经是RISC体系架构了!
为了解释内存对齐问题。必须知道其物理构造,关键并非怎样设计内存芯片,而是怎样将内存芯片的引脚和CPU引出的地址总线相应起来,怎样建立两者之间的关系是最重要的。别忘了,计算机在CPU之外要解决的唯一问题就是寻址问题!
假设数据是随意对齐的,那么在CPU发出寻址指令时,就可能出现数据存在两片芯片上的情况,而为了布线的简单,这样的寻址指令必须两次完毕,假设两次操作之间锁住总线。就会大大减少效率,假设不锁总线。就会有原子性问题。
要求编译器或者程序猿不写出那样的指令是最简单的,因此这个任务就落在了编译器或程序猿的头上。这就是为何在某些机器上数据一定要自然长度对齐。
UNIX之初
应用程序蓬勃发展的今天,非常难想到UNIX等分时系统在构建之初的目标。分时系统是为了让系统以一种流水线的方式取代批处理,让用户不必长时间等待。实际上当时的分时系统是以一种时间片错觉的方式展示给系统用户的。其实,系统的吞吐量和总的工作延迟并没有改善。改善的仅仅是人们对这样的错觉的认可。这就是最初的分时系统。那么UNIX呢?UNIX在非常多方面走得更远,对于AT&T来讲。它的电话业务是大头,它当然希望用一种性价比更加高的投资为用户提供一种基于错觉的服务方式,而用户根本就感觉不到这样的差异。贝尔实验室最初的分时系统并非去执行什么应用。而是为了控制语音通话,可是后来。它走向了终端。
电话用户非常easy和打印机。终端用户联系起来,由于它们都属于远程用户,共享同一主机资源。分时系统出现之前,要么等,要么建立并行系统。无论对于用户来讲,还是对于投资回报而言。都不是令人惬意的,分时系统攻克了全部的问题。文件抽象也是为了更方便的I/O,因此能够看到,早期的UNIX的I/O扮演了什么角色。正如现在的路由器,交换机一样,早期的UNIX在进程模型抽象层面提供控制平面,在文件抽象层面提供数据平面。它的内核就是为控制平面而生,而数据平面应该尽可能使用用户态的I/O来完毕,遵循这一原则的,将会得到回报,直到今天依旧如是。
幸运的是,今天非常多的厂商已经走向了这条路,也出现了非常多这样技术,实例PF_RING技术。而这一切,早在平原UNIX时代已经决定。
版权声明:本文博主原创文章。博客,未经同意不得转载。