笔记和练习博客总目录见:开始读TLPI

UNIX 系统的开发并非由单一厂商或组织控制,好处是带来很多创新,弊端则是众多分支导致编写能在所有 UNIX 实现上运行的应用程序非常困难(可移植性)。

UNIX商标的持有者是Open Group,其官方标准为SUS(Single UNIX Specification)。通过SUS认证的UNIX系统包括MacOS,HP-UX,IBM AIX等。Linux虽不在认证列表中,但被认为是类UNIX系统。
在这里插入图片描述

UNIX标准介绍参见这里

此网页还有UNIX发展简史图
在这里插入图片描述
UNIX Overview是配合上图的文字介绍。

1.1 A Brief History of UNIX and C

UNIX诞生于1969年(Linus Torvalds出生),最初用汇编语言编写,后来用C重写。C语言的目标就是用于实现 UNIX 内核及相关软件的高级语言。UNIX的C语言基因使得后来系统编程大多使用C语言。

1974 年 7 月,Dennis M. Ritchie 和 Ken Thompson在ACM上发表了论文:The UNIX Time-Sharing System

在1969年至1979年期间,UNIX经历了多个版本,这些版本被称为editions。其中第7版非常重要,不仅因为这一版提供了增强的文件系统,awk、sed、tar、bash等工具,而且从此版开始,形成了BSD和System V 两个分支(在上图中有体现,其中重点提了可移植性)。

BSD即Berkeley Software Distribution,起步于1975/1976学年,Ken Thompson 作为访问教授在加利福尼亚大学伯克利分校任教时,这所大学也是他毕业的学校。其中一个参与项目的学生Bill Joy后来成为Sun的联合创始人。所以SunOS实际带有BSD的基因。4.2BSD是一个重要的版本,因其包含了完整的TCP/IP实现,包括socket API。

美国的反垄断立法迫使 AT&T 解体后,UNIX被允许销售,这导致了1981年 System III(系统三)的发布,继而到1983年的System V。1989年发布了最终版本SVR4(System V Release 4),此时的System V也从BSD借鉴了很多特性。

简单来说,BSD和System V分别走的是学术和商业路线。一些路由器、存储、游戏机多使用BSD,其中macOS是目前最大的 BSD 商业应用。而HP-UX,AIX,Solaris,SCO OpenServer 等则源于System V。而Linux是独立内核,兼容 BSD + System V,但不直接源于两者。

总的来说,UNIX系统的可移植性及廉价单用户 UNIX 工作站的出现,使得 UNIX 系统从商业角度来看越来越具有吸引力。

💡 可移植性,兼容性,互操作性有何区别?可移植性关注Can I move it?,兼容性关注Can it co-exist?,互操作性关注Can it communicate?。对于应用软件而言,数据库从11g升级到19c,主要影响的是 兼容性,其次是互操作性。操作系统由AIX换为Linux,主要影响的是可移植性,其次是兼容性。而一些协议和API的变更(OAuth 1.0 → 2.0、TLS 版本升级),则主要影响互操作性。

1.2 A Brief History of Linux

1.2.1 The GNU Project

1984年,Richard Stallman,一位曾在麻省理工学院(MIT)工作的极有才华的程序员,开始着手创建一个“自由”的UNIX实现,目的是希望像操作系统这样的软件将以免费或极低的成本提供。
在这里插入图片描述

Free Software中的Free并非免费之意,正如在What is Free Software?的声明所说:

“自由软件”指的是尊重用户自由和社区的软件。大致来说,这意味着用户有权运行、复制、分发、研究、修改和改进软件。因此,“自由软件”关乎的是自由,而不是价格。要理解这个概念,你应该把“自由”理解为“言论自由”中的自由,而不是“免费啤酒”中的免费。我们有时称之为“libre 软件”,借用法语或西班牙语中表示自由的词,以表明我们并不是指软件是免费的。

你可能为获得自由软件的副本支付过费用,也可能免费获得过副本。但无论你是如何获得这些副本的,你始终拥有复制和修改软件的自由,甚至可以出售副本。

Stallman 反对计算机供应商对专有操作系统施加的法律限制。这些限制意味着计算机软件的购买者通常无法看到他们所购买软件的源代码,更不用说复制、修改或重新分发它了。他指出,这样的体系鼓励程序员相互竞争并囤积自己的工作,而不是合作和分享。

为此,Stallman 启动了GNU项目,GNU表示“GNU’s not UNIX”。也就是说接口、用法和 UNIX 完全一样,但代码完全重新写、完全自由开源。

GNU 项目的一个重要成果是 GNU 通用公共许可证 (GPL) 的制定,这是斯托曼自由软件理念的法律体现。Linux 发行版中的许多软件,包括内核,都是根据 GPL 或其他类似许可证发布的。根据 GPL 授权的软件必须以源代码形式提供,并且必须可以在 GPL 条款下自由再分发。对 GPL 授权的软件进行修改是完全允许的,但任何对这些修改后的软件的分发也必须遵守 GPL 条款。如果修改后的软件以可执行形式分发,作者还必须允许任何接收者选择以不超过分发成本的价钱获得修改后的源代码(源码不能卖钱,只能收 “分发成本”,即光盘、U 盘、邮寄、带宽这类物理 / 传输成本)。

到1990年代初,GNU项目已经开发出了一个几乎完整的系统,一些知名的项目包括Emacs文本编辑器、GCC、bash shell和glibc。唯一缺少的重要组件是一个可用的UNIX内核。

1.2.2 The Linux Kernel

1991年,芬兰赫尔辛基大学的学生林纳斯·托瓦尔兹(Linus Torvalds)受启发为他的Intel 80386电脑编写一个操作系统。因此,托瓦尔兹开始着手创建一个高效、功能齐全的UNIX内核,以运行在386上。然后,在1991年10月5日,托瓦尔兹请求其他程序员的帮助,并在comp.os.minix Usenet新闻组中发布了现在广为引用的关于他内核0.02版本的公告。

对支持的呼吁证明是有效的。其他程序员加入了托瓦兹(Torvalds)的Linux开发工作,添加了各种功能,例如改进的文件系统、网络支持、设备驱动程序和多处理器支持。到1994年3月,开发者们能够发布版本1.0。Linux 1.2于1995年3月发布,Linux 2.0于1996年6月发布,Linux 2.2于1999年1月发布,Linux 2.4于2001年1月发布。2.5开发内核的工作于2001年11月开始,并导致了Linux 2.6在2003年12月发布。

Linux 内核版本号
在 Linux 1.0 发布之后,内核开发人员采用了内核版本编号方案,每个版本编号为 x.y.z:x 表示主版本,y 表示该主版本中的次要版本,z 表示次要版本的修订(次要改进和错误修复)。

Linux 发行版
严格来说,术语 Linux 仅指由 Linus Torvalds 和其他人开发的内核。然而,Linux 这个术语通常被用来指内核,以及其他各种软件(工具和库),这些软件共同构成了一个完整的操作系统。

在Linux的早期阶段,用户需要自己组装所有软件,创建文件系统,并将所有软件正确地放置和配置在该文件系统上。这需要相当多的时间和专业知识。因此,出现了Linux发行商的市场,他们创建了软件包(发行版)来自动化大部分安装过程,创建文件系统并安装内核和其他所需的软件。然后就有了SUSE、Red Hat、Ubuntu等。

1.3 Standardization

到20世纪80年代后期,可用的UNIX实现种类繁多,但这也带来了弊端。一些UNIX实现基于BSD,另一些基于System V,还有一些则融合了两者的特性。此外,每个商业供应商都在其实现中添加了额外的功能。结果是,将软件和人员从一种UNIX实现迁移到另一种变得越来越困难。这种情况对C编程语言和UNIX系统的标准化形成了强烈压力,应用程序需要更容易地从一个系统移植到另一个系统。

1.3.1 The C Programming Language

到1980年代早期,C语言已经存在了十年,并且在各种UNIX系统以及其他操作系统上得到了实现。由于C语言的某些功能在现有事实上的标准——Kernighan和Ritchie于1978年出版的《C程序设计语言》中——没有详细说明,因此各个实现之间产生了一些小的差异。(书中描述的较旧的C语法有时被称为传统C或K&R C。)此外,1985年C++语言的出现突显了可以在不破坏现有程序的前提下对C进行的一些改进和扩展,尤其是函数原型、结构赋值、类型限定符(const和volatile)、枚举类型以及void关键字。

这些因素促使了对 C 语言标准化的推动,最终形成了C89 (1989年)或ISO C90(1990年,不太常见),并在 Kernighan 和 Ritchie 的《C 程序设计语言》(第二版,1988 年)中有完整描述。接下来的标准有C99(1999年),C11(2011年)等。

1.3.2 The First POSIX Standards

POSIX(可移植操作系统接口的缩写)一词指的是在电气和电子工程师协会(IEEE)的主持下开发的一组标准,特别是其可移植应用标准委员会(PASC,http://www.pasc.org/)。PASC 标准的目标是在源代码级别促进应用程序的可移植性。
POSIX 这一名称由理查德·斯托曼(Richard Stallman)提出。最后的 X 出现是因为大多数 UNIX 变体的名称都以 X 结尾。

对于我们的目的来说,最有趣的 POSIX 标准是第一个 POSIX 标准,称为 POSIX.1(或更完整地称为 POSIX 1003.1),以及随后发布的 POSIX.2 标准。

对原始 POSIX.1 标准的一些扩展也很重要。IEEE POSIX 1003.1b 于 1993 年批准,其中包含对基础 POSIX 标准的一系列实时扩展。IEEE POSIX 1003.1c 于 1995 年批准,是 POSIX 线程的定义。1996 年,发布了修订版 POSIX.1 标准,核心文本保持不变,但纳入了实时和线程扩展。IEEE POSIX 1003.1g定义了网络 API,包括套接字。IEEE POSIX 1003.1d于 1999 年批准,而 POSIX.1j 于 2000 年批准,定义了对 POSIX 基础标准的其他实时扩展。

POSIX.1b 实时扩展包括文件同步;异步 I/O;进程调度;高精度时钟和定时器;以及使用信号量、共享内存和消息队列进行的进程间通信。POSIX 前缀通常应用于这三种进程间通信方法,以将它们与类似但较旧的 System V 信号量、共享内存和消息队列区分开来。

FIPS 151-1 and FIPS 151-2
FIPS 是联邦信息处理标准(Federal Information Processing Standard)的缩写,是美国政府为其计算机系统采购指定的一套标准的名称。1989 年,FIPS 151-1 发布。该标准基于 1988 年的 IEEE POSIX.1 标准和 ANSI C 标准草案。FIPS 151-1 与 POSIX.1(1988)的主要区别在于,FIPS 标准要求一些 POSIX.1 留作可选的功能。由于美国政府是计算机系统的主要采购方,大多数计算机供应商都确保其 UNIX 系统符合 FIPS 151-1 版本的 POSIX.1 标准。

1.3.3 X/Open Company and The Open Group

X/Open公司是由一组国际计算机供应商组成的一个联盟,目的是采用和改编现有标准,以制定一套全面、一致的开放系统标准。它发布了X/Open可移植性指南,这是一系列基于POSIX标准的可移植性指南。

1996年,X/Open与开放软件基金会(OSF)合并,成立了开放集团(The Open Group)。几乎所有参与UNIX系统的公司或组织现在都是开放集团的成员,该集团继续开发API标准。

OSF是20世纪80年代末UNIX之战期间成立的两个厂商联盟之一。OSF的成员包括Digital、IBM、HP、Apollo、Bull、Nixdorf和Siemens等公司。OSF的成立主要是为了应对AT&T(UNIX的发源公司)与Sun(UNIX工作站市场最强大的玩家)之间的商业联盟所带来的威胁。因此,AT&T、Sun以及其他公司成立了竞争的UNIX International联盟。

1.3.4 SUSv3 and POSIX.1-2001

自1999年起,IEEE、开放组(The Open Group)和ISO/IEC联合技术委员会1在奥斯汀公共标准修订组(CSRG,http://www.opengroup.org/austin/)进行了合作,旨在修订和整合POSIX标准和单一UNIX规范。这导致POSIX 1003.1-2001的批准,有时仅称为POSIX.1-2001,于2001年12月正式批准(随后被作为ISO标准批准,ISO/IEC 9945:2002)。
POSIX 1003.1-2001取代了SUSv2、POSIX.1、POSIX.2以及许多其他早期的POSIX标准。该标准也被称为单一UNIX规范第3版,我们通常将其称为SUSv3

总的来说,SUSv3 中指定了 1742 个接口。相比之下,POSIX.1-1990(附 FIPS 151-2)指定了 199 个接口,而 POSIX.2-1992 指定了 130 个实用程序。SUSv3 可以通过 http://www.unix.org/version3/online.html 在线获取。经过 SUSv3 认证的 UNIX 实现可以称自己为 UNIX 03。

POSIX conformance, XSI conformance, and the XSI extension
从历史上看,SUS(以及XPG)标准遵循相应的POSIX标准,并被构建为POSIX的功能超集。除了规定额外的接口外,SUS标准还强制实现许多在POSIX中被视为可选的接口和行为。这种区别在POSIX 1003.1-2001中以更微妙的方式得以保留,该版本既是IEEE标准,也是开放组技术标准(即,如前所述,它是早期POSIX和SUS标准的整合)。该文档定义了两个符合性级别:

  • POSIX 一致性:这定义了符合标准的实现必须提供的接口基线。它允许实现提供其他可选接口。

  • X/Open 系统接口 (XSI) 一致性:要符合 XSI 标准,一个实现必须满足 POSIX 一致性的所有要求,并且必须提供一些对于 POSIX 一致性来说只是可选的接口和行为。一个实现必须达到这一一致性级别才能从开放组 (The Open Group) 获得 UNIX 03 品牌认证。

为了符合 XSI 标准所需的额外接口和行为统称为 XSI 扩展。它们包括对线程、mmap() 和 munmap()、dlopen API、资源限制、伪终端、System V IPC、syslog API、poll() 和登录帐户等功能的支持。在后面的章节中,当我们谈论 SUSv3 一致性时,我们指的是 XSI 一致性。

Unspecified and weakly specified
在 SUSv3 中,我们有时将接口称为“未指定”或“弱指定”。
未指定接口是指在正式标准中根本没有定义的接口,尽管在少数情况下,会有背景说明或理由文本提到该接口。
称接口为弱指定是简化的说法,意思是尽管该接口包含在标准中,但重要细节未被规定(通常是因为委员会成员由于现有实现的差异未能达成一致)。
在使用未指定或弱指定的接口时,将应用程序移植到其他 UNIX 实现时,我们几乎无法获得保障。然而,在少数情况下,这样的接口在各个实现之间相当一致,而当存在这种情况时,我们通常会注明。

LEGACY features
有时,我们注意到 SUSv3 将某个指定功能标记为遗留(LEGACY)。这个术语表示该功能是为了兼容旧应用程序而保留的,但其局限性意味着在新应用程序中应避免使用。在许多情况下,存在其他 API 可以提供同等的功能

1.3.5 SUSv4 and POSIX.1-2008

2008年,奥斯汀小组完成了对合并的POSIX.1和单一UNIX规范的修订。与上一版本的标准一样,它由基础规范和XSI扩展组成。我们将这次修订称为SUSv4。SUSv4的变化不如SUSv3那么广泛。

1.3.6 UNIX Standards Timeline

图 1-1 总结了前面各节中描述的各种标准之间的关系,并按时间顺序排列这些标准。在该图中,实线表示标准之间的直接衍生关系,虚线箭头表示一种标准对另一标准产生影响、被纳入另一标准的一部分,或只是参照另一标准的情况。

图1-1略。简化为以下关系:

层级 标准 作用 包含关系
最底层 ISO C C 语言本身 + 标准库(stdio、stdlib、string…) 所有上层标准都必须兼容 C 标准
中间层 POSIX.1 类 UNIX 系统调用接口(fork、open、read、pipe、signal、pthread…) POSIX ⊃ ISO C
上层 SUS (Single UNIX Specification) UNIX 官方完整规范,比 POSIX 更多接口 SUS ⊃ POSIX.1

💡 SUS属于Open Group,POSIX属于IEEE。POSIX 是基础接口标准,SUS 是 POSIX 的超集与官方 UNIX 认证标准;现代两者已高度融合,SUS = POSIX + XSI 扩展。

1.3.7 Implementation Standards

除了由独立或多方团体制定的标准之外,有时还会参考最终 BSD 版本(4.4BSD)和 AT&T 的 System V Release 4(SVR4)定义的两种实现标准。后者的实现标准通过 AT&T 发布的《System V 接口定义》(SVID)而正式确立。1989 年,AT&T 发布了 SVID 的第三版,该版本定义了 UNIX 实现必须提供的接口,以便能够称自己为 System V Release 4。(SVID 可在线获取,网址为 http://www.sco.com/developers/devspecs/)

由于某些系统调用和库函数的行为在 SVR4 和 BSD 之间有所不同,许多 UNIX 实现提供兼容性库和条件编译功能,以模拟在该特定实现中未作为基础使用的 UNIX 类型的行为(见第 3.6.1 节)。这减轻了将应用程序从另一个 UNIX 实现移植的负担。

1.3.8 Linux, Standards, and the Linux Standard Base

总体目标上,Linux(即内核、glibc 和工具)的开发旨在符合各种 UNIX 标准,尤其是 POSIX 和单一 UNIX 规范。然而,在撰写本文时,没有任何 Linux 发行版被开放组(The Open Group)正式标注为“UNIX”。问题在于时间和成本。每个厂商的发行版都需要经过一致性测试才能获得该标识,并且每次新发行版发布时都需要重复此测试。尽管如此,正是对各种标准的事实上的近似符合,使得 Linux 在 UNIX 市场上取得了如此的成功。

在大多数商业UNIX实现中,同一家公司既开发又分发操作系统。而在Linux中情况不同,实施与分发是分开的,多个组织——包括商业和非商业机构——负责Linux的分发。

由于存在多个 Linux 发行版,并且内核开发者并不控制发行版的内容,所以不存在所谓的“标准”商业 Linux。每个 Linux 发行版的内核通常基于某一特定时间点的主线(即 Torvalds 内核)快照,并应用了若干补丁。这些补丁通常提供某些功能,这些功能在不同程度上被认为具有商业价值,因此能够在市场上提供竞争差异。在某些情况下,这些补丁后来会被接受并合并到主线内核中。

前面几点的结论是,不同的 Linux 发行公司提供的系统之间存在(大多是轻微的)差异。Linux 标准基础(LSB)是一个旨在确保各种 Linux 发行版之间兼容性的努力。为此,LSB (http://www.linux-foundation.org/en/LSB) 制定并推广一套 Linux 系统标准,目的是确保二进制应用程序(即编译后的程序)可以在任何符合 LSB 的系统上运行。

LSB 提倡的二进制可移植性与 POSIX 提倡的源代码可移植性形成对比。源代码可移植性意味着我们可以编写一个 C 程序,然后在任何符合 POSIX 的系统上成功编译和运行它。二进制兼容性要求更高,并且在不同的硬件平台之间通常不可行。它允许我们为特定硬件平台编译程序一次,然后在该硬件平台上运行任何符合规范的实现。对于为 Linux 构建的独立软件供应商(ISV)应用程序来说,二进制可移植性是商业可行性的一个基本要求。

1.4 Summary

UNIX 系统最初于 1969 年由 Ken Thompson 在贝尔实验室(AT&T 的一部分)在一台 Digital PDP-7 小型计算机上实现。该操作系统从早期的 MULTICS 系统中借鉴了许多思想,也借用了其双关式的名字。到 1973 年,UNIX 已迁移到 PDP-11 小型计算机上,并用 C 语言重写,C 语言是由 Dennis Ritchie 在贝尔实验室设计和实现的。由于法律限制不能出售 UNIX,AT&T 改为以象征性费用将完整系统分发给各大学。这一分发包含了源代码,并在大学中非常受欢迎,因为它提供了一个廉价的操作系统,其代码可以被计算机科学的学者和学生研究和修改。

加利福尼亚大学伯克利分校在 UNIX 系统的发展中扮演了关键角色。在那里,Ken Thompson 和一些研究生扩展了该操作系统。到 1979 年,该大学已经制作出了自己的 UNIX 发行版 BSD。该发行版在学术界广泛应用,并成为多个商业实现的基础。

与此同时,AT&T 垄断的解体使公司能够销售 UNIX 系统。这导致了 UNIX 的另一个主要变体——System V 的出现,它也成为了几种商业实现的基础。

两条不同的路线促成了 (GNU/) Linux 的发展。其中一条是由理查德·斯托曼创建的 GNU 项目。到 1980 年代末,GNU 项目已经产生了几乎完整的、可自由分发的 UNIX 实现。唯一缺少的部分是一个可运行的内核。1991 年,受安德鲁·坦能鲍姆编写的 Minix 内核的启发,林纳斯·托瓦兹为 Intel x86-32 架构开发了一个可运行的 UNIX 内核。托瓦兹邀请其他程序员加入他,共同改进内核。许多程序员响应了这一邀请,随着时间的推移,Linux 得到了扩展,并被移植到各种硬件架构上。

到1980年代末,由于UNIX和C实现的差异引发的可移植性问题,造成了对标准化的强烈压力。C语言在1989年被标准化(C89),并在1999年发布了修订标准(C99)。首次尝试标准化操作系统接口产生了POSIX.1,该标准在1988年被批准为IEEE标准,并在1990年被批准为ISO标准。1990年代,进一步的标准草案被制定,包括各种版本的单一UNIX规范。2001年,合并的POSIX 1003.1-2001和SUSv3标准被批准。该标准整合并扩展了早期的各种POSIX标准和单一UNIX规范的早期版本。2008年,完成了一个范围较小的标准修订,产生了合并的POSIX 1003.1-2008和SUSv4标准。

与大多数商业 UNIX 实现不同,Linux 将实现与发行分开。因此,没有单一的“官方” Linux 发行版。每个 Linux 发行商提供的都是当前稳定内核的快照,并应用了各种补丁。LSB 开发并推广一套 Linux 系统标准,旨在确保二进制应用程序在不同 Linux 发行版之间的兼容性,使得编译后的应用程序能够在运行相同硬件的任何符合 LSB 的系统上运行。

1.5 Exercises

本章并无练习,这是我自己的问题。


1-1. 如何判断我的Linux符合哪个标准?

运行以下程序:

#include <stdio.h>
#include <unistd.h>
int main() {
    printf("_POSIX_VERSION = %ld\n", _POSIX_VERSION);
    printf("_XOPEN_VERSION = %ld\n", _XOPEN_VERSION);
    return 0;
}

输出为:

_POSIX_VERSION = 200809
_XOPEN_VERSION = 700

在这里插入图片描述
这里可知,SUS最新正式版是 SUSv4, 2018 Edition(UNIX V7),技术上对应 POSIX.1‑2017。这两个宏对应的正是最新版。之所以宏是 200809L,而非2018,是因为2017 不是全新标准,只是 2008 的 “最终修正版”。_POSIX_VERSION 只在基础标准大改版时才更新,后续的勘误、修正、整合版都不会改这个数字。

解读:
1)_POSIX_VERSION → POSIX 标准

  • 199009L → POSIX.1-1990(老)
  • 199506L → POSIX.1-1995
  • 200112L → POSIX.1-2001(SUSv3)
  • 200809L → POSIX.1-2008 / 2017(SUSv4,现代 Linux 默认)

2)_XOPEN_VERSION → SUS(UNIX 标准)

  • 600 → SUSv3 (UNIX 03)
  • 700 → SUSv4 (UNIX V7)

现代 Linux 几乎都是:POSIX.1-2008 / 2017(SUSv4)。

虽然没有任何Linux 做了 Open Group 的 SUS 官方认证,但glibc 的设计目标是尽可能兼容 SUSv4(POSIX.1-2008)。以上输出表明glibc(GNU C 库)在编译时,默认暴露了 SUSv4(UNIX V7)级别的接口。也即做到了开发层面的接口兼容,尽管不是系统层面的官方认证。

💡 关于标准的简述,可以参考man 7 standards

2026年3月2日读完,3月31日重读并修改

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐