作者:王垠
十年前的我的来信
今天收到一封 email,反对我在《一种新的操作系统设计》一文中提到的所有想法。让我想起一句话,每一个好的想法都要经受疯狂的反对。很感谢这位读者。他让我想起十年前的那个我。如果十年前那个我来到今天看到这篇文章,恐怕也会发这样的信给现在的我吧。见到年轻的我真好,所以把这封 email 记录在这里。它会鼓舞着我,它让我明白,我能做到很多人想象不到的事情,看到他们看不到的东西。
简单的概述
首先
看了一篇你的<一种新的操作系统设计>的文章!有一些简单的想法!希望可以与你交流一下! 只限于技术性探讨,没有其他意思和目的!言辞不当之处请谅解!同时水平有限有不当之处可以批评!(另外我看了你的Ydiff,如果以后有机会也可以聊聊)
文章是Markdown的,复制到邮件中或许会变形,如果看着不方便可以把原文档发给你!
我不理解你是如何理解"操作系统"这个概念的,也不明白你所谓的超越“Unix 哲学”是什么含义(但是你既然提到了Unix我就暂且认为你想要要的是运行于硬件的操作系统)。 但是我觉得你关于操作系统的理解完全是基于用户层面的.可以看出你是个理想主义者,希望系统按照自己想要的方式做事情!
你所说的11条操作系统的设想,是完全不靠谱的.有的甚至背离的"经典操作系统"的概念的,或者你设想的根本不能算一个操作系统而是架设在操作系统上的一层壳!(就像Hadoop一样是一个分布式'组织系统'),只不过Hadoop只解决了分布式计算(MapReduce)和分布式存储(HDFS),而你想要的更多,但也只是停留在操控层面的,你只是希望屏蔽一些底层的东西,让业务层面的变得更简单,或者看起来更简单(事实上不是每个人的思维方式都和你一样的,有些人认为面向对象的思维方式更自然,而有的人不是,一个完美主义者或者理想主义者总是试图找到一条普世的理论去阐释这个世界,于是有了"弦论",在科学界一是一,二是二的二元论断是非常值得推崇的,但是面对人性,面对需求你或许应该思考更多,爱因斯坦说上帝不玩骰子,然而他最终还是接受(至少是默许)了量子论,bash已经很好用了,却还有人鼓捣出各种各样的shell.)!
关于你文章对操作系统理解的总结:
通信是结构化的 一切都是用"超语言"定义的函数,所有的函数的规范是一元的 一切(系统本身,"函数程序",用户Shell程序)都用超语言实现,超语言不能有指针运算 用"对象数据库"取代关系数据库 不需要文件系统 用户透明与"无限" 为了避免数据移动产生的IO开销,优先自动迁移进程! 标题不好说
你的设计思路对操作系统没有任何现实意义,更多的是空中楼阁,水中月!是没有任何现实基础的"美好瞎想"!
你的文章中只有推翻,而没有建设!你只是说这个不要,那个不要(不要进程,不要文件系统,不要关系数据库...),而没有提供实际的可以取代他们的真正有意义的方案!
你的思维方式不是在设计一种操作系统,而是在设计一种编程语言!
按照你的理论:Python或者Java就是一个完美的操作系统!它几乎满足你要的一切!
超语言(上帝语言)的概念很吸引人,但这绝对是错误的!正如我上面所说人性和需求是复杂的,是动态的,是多变的,哪怕你提供是诸如"英语"一样的通用语言也会有很多人需要添加一个"中文翻译器"!完全不用翻译的意思就是你得要求所有人都遵循和接受你的思维方式!当然或许你会说这种超语言满足一切人的需求,拥有一切易用的特性!好吧,如果真的有上帝语言可以跟任何人沟通,我想还是会有很多人愿意尝试的!
你完全没有理解操作系统是什么,他扮演什么角色具体要处理哪些工作!你所要求的都只是操作系统的外延,而不是操作系统的内涵!你博客的文章标题或许变成<我需要这样一套分布式管理系统>或者<一种新编程语言的设计>更加合适!
就现在计算机的体系结构而言没有指针运算是不现实的,就架构而言现实机器大多是基于寄存器的,讨论基于堆栈的虚拟机对于设计和实现操作系统没有意义,事实上无论那种机型,想要快速随机的访问特定位置的数据间接寻址是一个非常不错的工具,除非你完全抛弃"间接寻址"!或许你在"语法解析"这种逻辑层面不需要这种特性,但系统层面的间接寻址是必须的,除非你设计一套新基于更高理论水平和哲学层次的硬件!
把系统看作为一个"仆人",只要对他下命令他就能按照你想要的方式为你做任何事情(这或许是你的终极目标或者是你目标的一种更为极端的表述)!只想用高级语言的特性而忽略计算机体系结构设想出来的东西根本就不能算作"典型意义上的操作系统"!按照你的方式我完全可以这样设计一个操作系统:只要我告诉他我想做什么,计算机就可以为我做任何事情,比如去厨房做个番茄炒蛋!他就傻乎乎的跑去买番茄和鸡蛋然后...这样的设计岂不是更完美?
我觉得你可能是做"语法分析"的!或许对各种语言的"哲学思想"有独到的见解,但是把这种思想或者更高层次的抽象带到"操作系统"的设计上就是很大职业病!为此你需要推翻现代计算机的体系结构,重新设计和研究可计算理论,不切实际的泛泛而论只会让我看到你的幼稚与任性,露脸与现眼只差一步!
如果你希望你做的是惊世骇俗,前五百年后五百年都不曾有和超越的东西.请先不要将它叫做"操作系统",或者跟"Unix哲学"比较!如果必须这样做,请先搞搞清楚什么事操作系统和Unix哲学!
我的一些相对现实与丑陋(没有那么理想化,很多甚至是迂腐)的看法
我理解的操作系统
最原始的需求:如果将计算机看作一堆冷冰冰的电子元件操作系统的角色就是"驱动,它将这堆冷冰冰的器件合理的组织起来,让他们构成一个系统团结起来工作;要知道程序是直接可以跑在机器上的,不需要任何系统的,但是这意味着你就必须面对这一堆冷冰冰的电子元件了! 我们要的更多:尽管硬件系统变越来越复杂,如果将计算机的计算能力,内存空间,外存空间等看作资源,然而这部分资源终究还是有限的;操作系统的目标是如何更有效的使用和管理这些资源!就因为资源有限所以才需要管理,才需要操作系统,当然你所设想的"无限空间",不需要"文件系统"这种概念完全是背离的! 基于以上两点,现在多数真正的操作系统是面向"硬件"的,如何高效的利用硬件是他们的重点!(宏内核与微内核的争论在这一点上看起来像是对立的,事实上确实是这样么?我觉得,孜孜不倦的挖掘计算机的潜力是每个系统开发者的目标与乐趣所在)
程序,进程与函数
什么是程序什么是进程?去掉进程的概念是不是意味着你需要用别的方法代替?函数吗?事实上他们完全不是一回事儿,进程概念的存在是为了让程序看起来是并行执行的(还是以上这一点,为了更有效的利用CPU资源)!
函数呢? 函数是一种"可计算模型"的表示方法(你完全可以用图灵机,lambda演算,寄存器模型,或者递归来代替,因为他们的本质是一样的)!
你只是用函数描述了计算方法,而进程是有时间考量的,可计算理论中并没有"时间"这个维度!你抛弃了进程,就势必要在函数的定义一个时间维度,在你的观念里函数是一切,它可以做任何事情!现实意义上的计算机更多的是基于寄存器模型和递归模型的,编译器大多数只是将函数表述翻译成寄存器表述或者递归表述,这个过程是一一对应的,他们都是静态的,编译器在这个过程无法给他附上时间维度.编译器不做,操作系统也不做,也就意味着程序员得在代码中加入控制调度的代码,好吧我们回到了最原始的时代了.(当然除非你假设CPU的计算能力是无限的,任何函数都是可以并行执行的,函数的执行是不需要时间的,函数之间的依赖关系是不存在的...就另当别论了)
"“系统调用”,只不过是调用另外一个函数,"对于你的轻蔑傲慢的语气我真的不想吐槽!事实上系统调用还真是调用另外一个函数,对于很多微内核系统虽然其实现是"基于消息"的,但是其外在依然表现为"过程调用"形式,对于被调用资源的实现也依然是个函数! 我不知道你是如何理解函数这个概念的,"任何可计算的问题都能用可计算模型(比如函数)来表示,而可计算模型之外的则是不可计算的",这或许看起来像句废话,但他确实证明你所说的,可计算的一切都可以是函数,但是仅此而已,没有任何外延了,如何安排计算,如何调度计算,可计算理论并没有给出任何有意义的说明;
当然实际问题要复杂的多,除了时间问题,还有你提到的权限问题等!
关于关系数据库与文件系统
系统不需要 SQL,不需要关系式数据库。
我需要强调一点:关系数据库并不仅仅是一个数据存储方案,也是一个数据"计算方案"(很多人用他是不是因为存储方便,事实上它存储不方便也限制多多,诸如数据必须是结构化的,对于树形的或者图形结构的数据还需要扁平化)! 数据存储的方案有很多,你可以直接将数据按一定的格式排版放到一个文件,可以使用键值模型存储简单的数据,或者将数据保存为特定通用格式(比如JSON,XML),或者有很多基于树形结构的文档数据库.基于图论的图形数据库(Neo4j)和狗屎的对象数据,当然也包括基于关系模型的关系数据库!(或许有一天有人会来个大一统,但是谁取代谁的说法显然是不靠谱的),他们各有各的优缺点,而关系数据库更是基于严谨成熟的关系数据理论构建的,他的数据结构简单,运算简介高效,不明白为什么有人会讨厌SQL,事实上他是最简洁方便直观的工具,他隐藏了很多计算细节,甚至你只需要告诉他我需要什么(而不是如何做),他就能很好的为你提供服务!
如果一切都是对象,随意的构造数据,存取无疑是最方便的),但构建在对象之上的算法就必须自己实现(这将会是灾难),相比于自己在对象之上实现算法,"构造结构化数据"显然更简单(或者机械化),基于成熟的关系数据理论也可以让你避免很多错误!我想这也是关系数据库占统治地位的主要原因!
对于文件系统,理解有很多种,基于磁盘的文件系统和构建于文件系统之上的"文件系统"!操作系统意义上的是前者,而后者大多数是是一些"虚拟文件系统",网络文件系统,或者分布式文件系统!后者更接近于"文件管理系统",他没有解决数据如何存储在物理介质上的问题,主要面向业务,提供"文件系统透明"这一概念!操作系统设计提出"不要文件系统"和"金三胖不要姑父"一样荒唐!
解码是必须的
解码(解析)是一个"理解数据"的过程!
你可以把任何数据看作一个"有特定语意的对象",作为人很容易凭直觉和经验认定12345是数字,abcde是字母!但对于计算机他只是一块放在特定位置的"没有特定意义"的"数据",我们使用数据就必须对其赋予一定的含义,知道他是什么,如何组织!计算机不会下意识的知道12345是数字,而abcde是字母!理解数据必须存在,哪怕是一个结构化的数据,要使用它你就必须理解他,同时要让计算机理解他!(事实上你在判断12345是数字之前已经对他做了解码了)
所以我的结论是:解码是必须的!不是所有事情都是理所应当的, 或许向你这样的人思维速度非常快,有些问题你凭直觉和经验就得出了结论!以至于你甚至意识不到你对问题做出了思考!但是理性是必然存在的!
那么这个问题就变成了"谁来解码"!
目前而言可以有下面几个选择:
计算机自己(硬件系统和操作系统)
事实上计算机有一定的解析数据的能力 就冯诺依曼体系结构的计算机而言,它要求程序按照特定的指令系统被编码存放,这种规范的是一个有限的集合!无限延伸让他处理任何的数据是不可能的(比如你给计算机一个Torrent文件他或许只是个文本,但让计算机知道接下来要做什么是不可能的,不可能任何系统都安装了这个解码器,因为不是所有人都需要的,你必须许更具特定的需求自己安装Bencode/Bdecode)!更高层次的解析(理解)需要具体问题具体处理,除非你颠覆现有的体系结构重新设计基于更高理论水平和哲学层次的可计算模型. 把所有的东西交给系统来处是不切实际且没有必要的(如果特定场景或许可以),所以你或许应该把这些事情交给下面的选项来做!
编译器(或者解释器) 当我们编译一个C的结构体的时候,编译器提供了编码和解码,它根据语法定义的数据的宽度得到特定偏移,将数据按照特定偏移排布在特定的位置这是一个编码的过程,计算机根据自己的指令系统的定义和规范对编码的数据进行加载和运算,这是一个解码的过程!从函数式编译到寄存器模型亦是一个翻译的过程,这个翻译过程为了让不同系统之间相互交流编码和解码是不可避免的!
程序库
我们很容易的使用已有的库去解析JSON,XML,让他们变成你所谓的对象,应为你或许觉得在用户层面上使用对象的概念会更简单!
用户(程序员): 对前无古人的个性化数据赋予一定的语意,用户必须制定特定的格式或者协议,然后手动编写相应的代码实现编码与解析!然而这是大多数创造力的来源!如果你做创造性的工作,我想这会是大多数情况!
关于如何解决分布式问题
你提到的移动"计算"优于"移动数据",这在大多数情况下是正确,包括Hadoop这种系统也是那么做的,这并无新意!
然而事实上分布式问题的核心在于调度,在于如何抽象成一个分布式计算模型来一劳永逸的解决任何可分布式计算的问题,在这里还要明确一点有很多问题是不可分布式计算的,就是因为存在这种问题,构建一劳永逸的模型就几乎成为不可能的至少是有代价的事情,MapReduce或许是一个很不错的模型,但在特定的情景下依然会显得力不从心,同时无可避免的引入了无关代码去分解问题(只是将这个过程模式化了),很多情况下特定的业务逻辑下,这种方案并不是最高效的.
而Java和其他一些分布式方案并不是真正意义上的"分布式模型",他并没有解决任何"问题分解"和"调度"的问题,程序员仍然需要根据自己的业务需求分解简化问题,决定哪些问题在哪些节点运行,何时运行!
不需要显式的使用特定的方法就能让系统跟安排进程执行一样自动的分布这些计算和数据到不同的节点的通用系统我没见过(或许还真有)!