一切皆文件的设计,也就是在PC/服务器市场的的类Unix操作系统里设计的比较成功。个人用户里,Windows就不是这样的设计,你能说Windows不成功吗?
一切皆文件,其实就是把操作系统的设备/资源接口统一化,但并不代表统一化,就一定需要一切皆文件。
况且,接口统一化,仅仅是对操作系统驱动、底层应用开发有帮助,并不代表接口统一化一定没缺点。
一切皆文件,会导致操作系统内核的尺寸变大(文件系统本身接口过于庞大),为了适配文件系统接口,不管什么类型的驱动,都要做成面向文件的操作,有可能导致原本很简单的驱动,设计变得复杂。对于CPU比较弱,存储比较少的设备来说,接口统一化可以说是一个缺点(为了统一接口做额外工作),而不是优点。
很多嵌入式操作系统,并不是按照一切皆文件的思路设计的。嵌入式系统,甚至连基本的文件系统操作都可以剪裁掉,此时一切皆文件就并不适用了。
况且,Linux里也有一堆并不使用文件接口访问的设备和框架。
再说C++的流式IO问题:
操作系统要搞接口统一,是因为硬件种类和驱动类型太多,对于驱动和应用开发不方便,是为了解决问题而提出的设计。驱动开发,希望有一个统一的接口。把不同的东西统一化。
流式IO的应用场景,是应用开发,应用开发的最大特点是需求多样化,但流式IO并没有用一个接口做更多不同的事情,相反,它限制了应用的功能,这种设计显然是不成功的。
很简单:
一切皆文件是底层设计思想,是把复杂问题简单化,从而写出“明显不可能错”的代码。
而C++的流式IO是强行统一高层接口,是把简单问题复杂化,因此不得不实现的极为复杂笨重,和C/C++库一贯轻灵极简的风格格格不入。
打个比方的话,“一切皆文件”相当于标准化发动机,一切(动力输出)皆旋转,转速扭矩一匹配,随便蒸汽机汽油机还是电动机,拿来都能用。
而流式IO则是“操控界面旋转化”:转向?拧!挂挡?拧!加大油门?拧!刹车?拧!离合?拧!鸣笛?拧!
你看,的确能做到“一切皆拧”,但这种拧是无意义的,不符合人体工学的;而且加大了设计难度,复杂化了刹车/离合的内部结构,降低了可靠性。
那么,为什么同样是“一切皆XX”系列的抽象,一个极度成功另一个却惨遭失败呢?
很简单,一个抽象在“根”上,一个抽象在“梢”上。
一切皆文件抓住的是“计算机里的所有操作其实都是图灵机里的喂纸带”这个根本,于是拿“一切皆文件(IO)”做了个概括;那么将来使用时就不需要一边考虑“这个设备的工作原理/控制原理”,一边纠结“它的接口风格可能是什么样子”(比如需不需要先prepareDev/InitialDev然后设置缓冲区的接口是setBuf/setCache/useMemory呢还是其它)——很简单,全都是文件风格的操作界面,有无缓冲区用字符设备/块设备区分;只是随着设备不同,同样写点东西进去动作不同(这个得查设备手册,没人能保证连这个都统一了)。
这不就是多态吗?
你看,思维负担一下子砍下去一半,多轻松。
但流式IO呢?你见过用流式IO操控设备的吗?
当然不能。因为操控设备要发命令字,做成流式IO就麻烦了。fopen然后fwrite直接写端口多方便,对吧。
它统一的是什么呢?
没错,程序内部产生的各种信息的(文件)读写/写屏/读键盘输入等操作。
可这个领域,不正是最需要百花齐放的地方吗?你怎么统一它?
我搞了个文件数据库,改写某条记录;过去fseek到这条记录然后fwrite,多清晰多简洁;现在呢?没错,能支持,我知道;但在流上fseek是什么鬼。这个抽象也太别扭了吧?一会儿是流你<<往里灌就是,一会儿是文件你可以fseek……搞了半天不还是文件抽象吗?
哦,你最好借助C的fopen/fseek系列函数学会文件IO,然后把它转换成别扭的流式操作风格?
说你是语法糖吧,你不仅不减少思维负担、提供书写便利,你还抬高了学习台阶、增加了思维负担——我不用想就知道文件如何操作,所以必须查一查流里面的对应物,看看现在它变成了什么?
你看,一切皆文件砍了一半思维负担,一切皆流给你加了一半思维负担。
为了这么个语法糖不算语法糖的东西,整了那么一套复杂的流库……
尤其是,现在是GUI时代了。屏幕输出都写哪了?
没错。文本框,富文本框,下拉框,标签……怎么流?
啊啊?是让我写?让我把富文本框标红一段内容设计成流式风格?
我傻?
你看,矫揉造作,四六不着。
所以才说这个抽象在“梢”上:看起来很酷,但没有半点通用性、预见性——甚至连老本行都做的矫揉造作,使得只有傻子/疯子才会把自己新设计的东西的接口向它靠拢;除了它,计算机世界的一切都是函数调用风格,于是学习它所投入的精力回报更少、那么就更不值得为它耗费精力(作为对比,一切皆文件把一切设备的操控接口统一成了文件风格,将来设计驱动时简单,填充文件操控对应的回调就行;别人学习使用也简单,看看你的命令字然后像文件一样就行:你看,一份投入,无穷回报)。
这能流行才怪。