Linux 之前的 Unix 桌面沉浮启示录
It takes more than open source, it takes open standards and consensus
仅仅开源还不足以实现开放,还需开放标准和建立共识
Steven J. Vaughan-Nichols
Sat 27 Jan 2024 // 12:33 UTC
现在,由于有了安卓和 ChromeOS,Linux 已成为重要的终端用户操作系统。但在 Linux 之前,Unix 桌面起着重要的作用,尽管大多数并未留存至今。
追溯至 1993 年,我在 《PC Magazine》上做了一篇 Unix 桌面的特性评测。是的,在我成为 Linux 桌面用户之前,我是 Unix 的使用者。自从 1979 年 2BSD Unix 出现以来,我就是 Unix 的忠实拥趸。到了 1993 年,Unix 桌面繁多,我成功说服我们的杂志让我试用它们。
我和我的团队评测了来自 Consensys、Dell、Interactive Unix、SCO、Univel、昇阳Sun,和 NeXT 的 Unix 版本。我们也注意到了来自 UHC、Microport 和其它公司的 Unix,但没有进行评测。我相信你们中的大多数人都未曾听说过这些。
那 Linux 呢?那时候,Linux 已经问世,而且我也使用过。但当时最先进的 Linux 发行版是 Softlanding Linux System(SLS),我无法说服编辑们 —— 或者说我自己,认为它是值得评测的。我本可以评测的第一个版本是 Slackware,它至今仍在我们身边,但在那时候,它的发布日期还有数月之遥。
现如今,只有 Dell 仍然存在,不过它之所以至今仍在业界,不完全是因为它的 System V Release 4(SVR4)Unix 发行版。然而,那些早期的 Unix 桌面中,仍有一个仍然活跃健康,且运行在大约 四分之一的桌面 上。
那个操作系统,当然,就是 macOS X,它是 NeXT 的 NeXTSTEP 的直接后裔。你可以说基于多线程、多进程微内核操作系统 Mach、BSD Unix,和开源的 Darwin 的 macOS,是所有 Unix 操作系统中最成功的。
但在当时看来,情况并非如此。并不是因为 Windows 比 Unix 更好。在 1993 年,可以称作 Unix 的竞争对手的只是 Windows 3.1 和 NT 3.1。
特别是 NT,在那时,它只能算是个笑料级别的服务器操作系统。直到 Windows NT 3.5 发布后,NT 才开始变得重要。
Windows 击败 Unix 的原因多种多样。其中最重要的一点就是微软确保所有硬件和软件供应商要么与它对齐,要么就无法 使用 Windows 或微软 Office。
那个时候,这是个极其重要的问题。我们如今看待 Mac,通常将其视为等同于或者超过 Windows PC 的竞争对手。但那个时期的情况并非如此。史蒂夫·乔布斯当时已被解雇,并且在苹果公司 1993 年的年度报告中,该公司报告显示其 净收入已下降了97%。
然而,尽管微软的成功在很大程度上得益于其历史上的 不正当商业行为,但它并非靠不正当手段得以胜出。Unix 公司正在自我毁灭。
尽管有许多为 Unix 创立软件开发标准的尝试,但它们或者过于宽泛而无法做出实质性贡献,例如 POSIX;或者它们在开放系统基金会Open Systems Foundation 和 Unix 国际Unix International 之间的商业联盟争端中陷入僵局,这就是著名的 Unix 战争。
在 Unix 公司忙于内斗的同时,微软正乐得财源滚滚。关键问题在于 Unix 公司无法就软件标准达成一致。独立软件开发商(ISV)需要为每一个 Unix 平台编写应用。而这些应用在桌面市场的份额都微乎其微。对开发者来说,为 SCO OpenDesktop(也被称为 OpenDeathtrap)、NeXTStep,以及 SunOS 分别编写一个版本的应用程序,从商业的角度来看,这完全没有意义。
这种情况听起来似曾相识吗?这种问题如今依旧困扰着 Linux 桌面,这也是我对诸如红帽的 Flatpak 和 Canonical 的 Snap 这样的 Linux 容器化桌面应用如此钟情的原因。
等到双方于 1996 年最终在 The Open Group 合力和解时,已经为时已晚。Unix 在传统桌面上的市场被挤压出局,工作站基本上都变成了 昇阳微系统Sun Microsystems 的天下。
那么,Linux 是如何崭露头角的呢?实际上,相比 Unix 发行版,它有两个主要的优点。首先,它是开源的。在开源的优胜劣汰机制下,好的代码能够生存,差的代码将被淘汰。我认为 Linux 使用 GPL,这点非常关键。
毕竟,如果成功只需要开源代码,那么我们现在都应该在运行如 FreeBSD、DragonflyBSD 以及 GhostBSD 这类纯 BSD 操作系统。但是实际情况却是,虽然 BSD Unix 系统至今仍然重要,却远远比不上 Linux 的市场份额。
Linux 基金会的开源供应链安全主任 David Wheeler 解释了这个原因:BSD 许可证存在的问题在于每隔几年就会有人说:“嘿,让我们基于这个 BSD 代码 开一家公司!”他们会利用这些 *BSD 代码,某些最优秀的 BSD 开发者,然后开发出一款专有的派生产品。但作为专有厂商,他们的分支成本高昂,维护不易,因此公司最终走向破产……如此反复。
“而与此同时,GPL 通过法律约束将大型商业公司聚集在一起……他们所有人都在作出贡献,并且感到安心,因为他们知道他人也被法律要求必须同样做。这就创造了一个安全的合作区。”
Linux 的另一大优势便是其领导,Linus Torvalds。有了 Torvalds 这唯一领导,Linux 规避了 Unix 陷入的内斗困境。
然而 Torvalds 的积极力量并不只在于他是一位天才开发者。尽管他的头衔可能笑称为“终生仁慈独裁者 Benevolent Dictator for Life”,多年来,Torvalds 已经学会了如何与他人和谐合作。
有些人说,Torvalds 的人缘不够好,的确,他并不宽容对待愚蠢的行为。然而,我多次参加过 Linux Plumbers 会议,他和顶尖的 Linux 内核开发者们的合作过程中,我并未见到他们之间有过什么明显的矛盾。如今的 Linux 已是一个集体的功劳。
如果 Linux 的未来全都寄托在 Torvalds 一人身上,我也会担心 Linux 的未来。Torvalds 无疑是一位杰出的人才,一个伟大的程序员,但如果这就是 Linux 成功的全部,我们就会陷入一个痛苦的问题:一场公交车事故,就会让我们失去整个 Linux。
幸运的是,Linux 的发行者和开发者们从 Unix 的历史中汲取了教训。
他们清楚,拥有一款成功的桌面操作系统,需要的不仅仅是开源,还需要开放的标准和共识。
我们可能永远都无法迎来那个传说中的 “Linux 桌面年”,但通过安卓和 Chrome OS,Linux 已然成为顶级的终端用户操作系统。经过漫长的等待,Unix 终于通过 Linux 成为了一款顶级的终端用户操作系统。
via: The Land Before Linux: The Unix desktops
https://www.theregister.com/2024/01/27/opinion_column
2024-01-29 10:30 原文作者:Steven J. Vaughan-Nichols
译者:ChatGPT 校对:wxy 本文由 LCTT 原创翻译,Linux中国 荣誉推出
相关文章:
Linux 之前的 Unix 桌面沉浮启示录
It takes more than open source, it takes open standards and consensus 仅仅开源还不足以实现开放,还需开放标准和建立共识 Steven J. Vaughan-Nichols Sat 27 Jan 2024 // 12:33 UTC 现在,由于有了安卓和 ChromeOS,Linux 已成为重要的终端…...
面试问题梳理:项目中防止配置中的密码泄露-Jasypt
背景 想起面试的时候,面试官问我现在大家用Spring框架,数据库、ES之类的密码都是配置在配置文件中的,有很大的安全隐患,你有考虑过怎么解决嘛? 当时我回答是可以在项目启动的过程中的命令行追加的方式,感觉…...
engine.addImportPath()用于向 QML 引擎添加新的模块搜索路径
engine.addImportPath() 是 QQmlApplicationEngine 类中的一个方法,用于向 QML 引擎添加新的模块搜索路径。这在需要加载自定义模块或从非标准位置加载 QML 文件时非常有用。通过使用 addImportPath() 方法,可以让 QML 引擎在额外的路径中查找 QML 模块。…...

ServiceNow UI Jelly模板注入漏洞复现(CVE-2024-4879)
0x01 产品简介 ServiceNow 是一个业务转型平台。通过平台上的各个模块,ServiceNow 可用于从人力资源和员工管理到自动化工作流程或作为知识库等各种用途。 0x02 漏洞概述 由于ServiceNow的Jelly模板输入验证不严格,导致未经身份验证的远程攻击者可通过构造恶意请求利用,在…...

项目部署笔记
1、安全组需开放(如果不开放配置nginx也访问不到) 2、域名解析配置IP(子域名也需配置IP,IP地址可以不同) 3、如果出现图片获其他的文件找不到的情况请仔细检查一下路径是否正确 4、服务器nginx配置SSL证书后启动报错: nginx: […...
PyCharm\VsCode——Python第三方库下载换源
为什么要换源? Python第三方库下载默认镜像源在国外,因为特殊的原因在国内的你我利用这个镜像源往往速度会非常地慢,因此为了提速将这个默认镜像源换成国内的镜像源是非常有必要的。 镜像源的种类有哪些? 国外镜像源——官方 http…...

图片上传裁剪react-cropper
效果图 安装插件 npm i react-cropper 或者 yarn add react-cropper 主要代码 import React, { useRef, useState } from react; import Cropper from react-cropper; import cropperjs/dist/cropper.css; import ./index.less; import { UploadOutlined } from ant-d…...
跨越空间的编码:在PyCharm中高效使用远程解释器
跨越空间的编码:在PyCharm中高效使用远程解释器 PyCharm的强大功能之一是支持远程解释器,这使得开发者能够在远程服务器或虚拟机上运行、调试代码,享受本地开发环境的便利。本文将详细介绍如何在PyCharm中配置和使用远程解释器,包…...
Vue3单文件jsx输出多组件示例遇到的坑
感谢博主减肥吧Evan提供的SFC实现多组件的思路和实现,小卷在大佬的基础上再完善下实现。 我们从tsx的API使用上得到启发,可以在vue的单文件组件(sfc)中使用defineComponent来定义和导出多个独立的小组件。此时sfc中的<templat…...
OpenCV中的轮廓检测cv2.findContours()
文章目录 前言一、查找轮廓二、绘制轮廓轮廓面积轮廓周长 前言 轮廓提取的前提,将背景置为黑色,目标为白色(利用二值化或Canny) 边缘检测,例如Canny等,利用梯度变化,记录图像中的边缘像素点&a…...

JFlash读取和烧录加密stm32程序
JFlash读取和烧录加密stm32程序 安装后JFlash所在的目录:C:\Program Files\SEGGER\JLink 一、烧写加密程序 1、打开C:\Program Files\SEGGER\JLink目录,找到JFlash.exe,双击它,就可以打开该执行程序。见下图: 2、选择“Create …...

【总结】实际业务场景中锁、事务、异常如何考虑使用?
文章目录 锁处理目的:考虑锁控制思路:生命周期接口并发控制解决方案:测试锁是否生效:模拟多线程并发场景的2种方式: 事务处理目的:考虑事务控制思路:解决方案: 总结 锁处理 目的&am…...

Pytorch使用Dataset加载数据
1、前言: 在阅读之前,需要配置好对应pytorch版本。 对于一般学习,使用cpu版本的即可。参考教程点我 导入pytorch包,使用如下命令即可。 import torch # 注意虽然叫pytorch,但是在引用时是引用torch2、神经网络获取…...
【nginx】nginx的优点
目录 一、高性能1.1 高并发处理1.2 低内存消耗1.3 快速响应 二、高扩展性2.1 模块化设计2.2 动态模块扩展 三、高可靠性3.1 核心框架稳定3.2 进程管理3.3 负载均衡与健康检查3.4 热部署 四、功能丰富4.1 反向代理4.2 HTTP缓存4.3 安全功能 五、易于配置和管理5.1 配置文件简单5…...

K8S ingress 初体验 - ingress-ngnix 的安装与使用
准备环境 先把 google 的vm 跑起来… gatemanMoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-user$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 124d v1.23.6 k8s-no…...
qt 获取父控件
在 Qt 中,你可以通过调用 QWidget 的 parentWidget() 方法来获取一个控件的父控件。这个方法会返回一个指向父控件的指针,如果该控件没有父控件,则返回 nullptr。 以下是一个简单的示例,展示了如何获取一个按钮的父控件ÿ…...
flask基础配置详情
前言 一个简单的应用 app Flask(__name__) app.route("/") def hello_world():return "<p>Hello,World!"运行Flask应用 #flask命令运行flask --app hello run#使用Python命令进行运行python -m flask # 作为一个捷径,如果文件名为 app…...

单相整流-TI视频课笔记
目录 1、单相半波整流 1.1、单相半波----电容滤波---超轻负载 1.2、单相半波----电容滤波---轻负载 1.3、单相半波----电容滤波---重负载 2、全波整流 2.1、全波整流的仿真 2.2、半波与全波滤波的对比 3、全桥整流电路 3.1、全波和全桥整流对比 3.2、半波全波和全桥…...
用GPT 4o提高效率
**GPT-4o可以通过提高编程效率、优化工作流程、增强文档管理和知识分享等多方面帮助用户提升工作效率**。具体如下: 1. **代码生成与优化** - **快速原型开发**:程序员可以通过向GPT-4o描述需求或功能来生成初步的代码框架或关键函数,从而节省…...

20240711每日消息队列-------------MQ消息的积压的折磨
目标 解决MQ消息的积压 背景 菜馆系统----------- 系统读取消息,处理业务逻辑,持久化订单和菜品数据,然后将其显示在菜品管理客户端上。 最初我们的用户基数很小,上线后的一段时间内,MQ消息通信还算顺利。 随着用户…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...