# 相关概念
# 操作系统
使用计算机有两大条件:
- 准备一套计算机硬件,至少包括 CPU、内存,通常还包括硬盘、显示器、键盘等设备。
- 在内存中写入一套操作系统的代码,由 CPU 执行。
- 例如,用户购买一个笔记本电脑,通常内置了操作系统的代码。只要连通电源、按下开机键,就会自动执行操作系统。
目前世界上流行的操作系统举例:
- Linux :开源
- Windows :闭源,收费
- Darwin :闭源,收费
- Android :开源
# Unix
1964 年,贝尔实验室、麻省理工学院、通用电气公司开始合作研发一个分时操作系统 Multics 。
- 传统的操作系统,同时只能供一人使用。而 Multics 系统的设计目标,是安装在通用电力公司的大型计算机上,支持几百个用户同时使用。
- Multics 项目发明了多项新技术,比如动态链接、分层文件系统。
1966 年,Ken Thompson 从加州大学伯克利分校毕业,加入贝尔实验室,参与研发 Multics 。
- 在研发 Multics 的过程中,Ken Thompson 在 Multics 系统中编写了一个名为 "Space Travel" 的小游戏。
1969 年,Multics 项目变得越来越复杂,难以完成,于是贝尔实验室决定退出该项目。
- 退出 Multics 项目之后,不能再使用昂贵的大型计算机。因此,Ken Thompson 将他的小游戏,移植到另一台老旧的 PDP-7 小型计算机上。
- 移植的过程是:
- 借鉴 Multics 系统的设计思路,用 PDP-7 汇编语言开发了一个新操作系统,取名为 Unix 。
- 借鉴 BCPL 语言,发明了 B 语言。然后用 B 语言混合汇编语言,在 Unix 系统中开发程序。
1972 年,因为使用 B 语言开发程序依然麻烦(比如没有数据类型),Ken Thompson 和 Dennis Ritchie 将 B 这个解释型语言,改进为一个编译型语言,称为 C 语言。
- 然后他们用 C 语言重写了 Unix 系统。
- 他们吸取了 Multics 项目的教训,在设计 Unix 系统时采用 "Keep it simple and stupid" 的原则:将复杂的程序拆分成多个小模块,然后组合使用。
1978 年,Brian Kernighan 和 Dennis Ritchie 出版书籍《The C Programming Language》,将 C 语言介绍给全世界。
- 这是第一本介绍 C 语言编程的书籍,书中的第一个示例程序是显示 "hello world" ,成为了众多编程语言教程的传统。
- 这本书中描述的 C 语言,此时还没有正式的语法标准,称为 "K&R C" 。
随着 C 语言的推广使用,Unix 系统也被传播开来。
- 1980 年代,贝尔实验室所属的 AT&T 公司将 Unix 作为闭源的商业软件发售。当时用户对 Unix 进行研究、改动,衍生了多种闭源的操作系统,但这些操作系统之间差异越来越大、不兼容。于是人们制定了 UNIX 规范和 POSIX 规范,希望这些操作系统遵守统一的规范。
- 1990 年代,一些人借鉴 Unix 系统,开发了一些新的操作系统。它们统称为类 Unix 系统,与 Unix 相似,但不符合 Unix 规范,源代码也不同。
- Unix 因为闭源,一直用户少。反而某些类 Unix 系统更流行。
- 目前,Unix 系统主要有两个分支:
- System V :由贝尔实验室所属的 AT&T 公司开发,属于闭源的商业软件。
- BSD :由加州大学伯克利分校开发,基于贝尔实验室的 Unix 源码,属于自由软件。其中最流行的一个发行版是 OpenBSD 。
# Linux
- 1991 年,芬兰的大学生 Linus Torvalds 开发了一个类 Unix 系统,取名为 Linux 。
- Linux 最初只有一个内核。Linus 将它按 GPL 协议授权为自由软件,吸引了其他人参与开发,形成了一个积极的社区。
- 后来,Linux 内核与诸多 GNU 软件组合在一起,构成了一个功能完善的操作系统,称为 GNU/Linux 。严格来说,Linux 并不是一个操作系统,只是操作系统的内核。
- 2007 年,开源发展实验室(Open Source Development Labs ,OSDL)与自由标准组织(Free Standards Group ,FSG)合并,成立 Linux 基金会,负责管理 Linux 社区。
# Darwin
- 一个开源的类 Unix 系统,其内核称为 XNU (X is Not Unix),混合了 Mach 内核、FreeBSD 组件。
- 由 Apple 公司开发,用作 MacOS、IOS 系统的底层。
- MacOS 系统(原名为 Mac OS X ,缩写为 OS X )
- 用作 Apple 公司生产的 Macintosh (简称为 Mac )品牌电脑的专用系统。
- IOS 系统
- 用作 Apple 公司生产的 iPhone 手机、iPad 平板的专用系统。
- MacOS 系统(原名为 Mac OS X ,缩写为 OS X )
- 关于应用程序:
- 安装包的扩展名:
- .dmg :一种压缩文件格式,类似于 .iso ,
- .pkg :一种安装包格式。
- 包管理工具:
- Mac App Store
- Homebrew :提供了命令行工具 brew 。
- 开发语言:
- Objective-C
- 一种编译型语言,在 ANSI C 的基础上增加了 Smalltalk 语言的特性,支持面向对象编程。
- 于 1983 年由美国人 Brad Cox 发明。
- C++
- 可以基于 Qt 开发程序。
- Swift
- 于 2014 年由 Apple 公司发布,目标为取代 Objective-C 。
- Objective-C
- 安装包的扩展名:
# Android
- 于 2007 年由 Google 公司发布,主要用于智能手机、平板电脑等小型移动设备。
- 该操作系统的内核是 Linux 内核,底层软件采用 C 和汇编语言开发,上层软件采用 Java 语言开发。
- 底层软件与 Linux 系统的差异较大。例如用 Bionic 库替换了 GNU C 库,因为 Bionic 库的体积、内存开销更小。
- 在 Android Open Source Project(AOSP)项目中开源,采用 Apache License 开源协议。
- 虽然 Android 系统开源,但安装了该系统的设备,一般还会安装一些专有软件,比如 Google 移动服务(GMS)、Google Play 。
- 关于应用程序:
- 安装包的扩展名:
- .apk
- 包管理工具:
- 各种平台提供的 Appstore ,比如 Google Play 。
- 开发语言:
- Java
- 运行在专为 Android 设计的 JVM 上,称为 dalvik 。
- C++
- 可采用 Qt 或 Android Native Development Kit(NDK)开发程序,但是开发过程比平台原生语言麻烦。
- Kotlin
- 一种编译型语言,可以编译成 Java 字节码或 JavaScript 。
- 于 2011 年由 JetBrains 公司发布。
- 2019 年,Google 公司宣布 Kotlin 取代 Java 成为了 Android 的首选开发语言。
- Java
- 安装包的扩展名:
# 接口
开发一个软件程序,应该对外提供一些接口(interface),供用户使用。每个接口用于实现一项功能。
根据外观的不同,将接口分为几类:
ABI(Application Binary Interface ,程序二进制接口)
- :调用这种接口时,需要按某种格式编写一段二进制数据。
- 例:
- 编译器将 C 语言编译成汇编语言时,有很多 ABI 层面的规定,例如每个数据类型的容量、使用哪些寄存器。
API(Application Programming Interface ,程序编程接口)
- :调用这种接口时,需要按某种编程语言编写一段代码。
- 例:
- 一个 C 语言程序可以在头文件中声明函数形式的 API ,供其它程序调用。
- 一个 MySQL 数据库提供 TCP 形式的 API 。
- 一个 Web 服务器提供 HTTP 形式的 API ,供其它程序发出 HTTP 请求来调用。
- 如果程序 A 提供了某个 API ,程序 B 也提供了相同的 API ,则其它程序可以通过相同的方式(比如用同一段代码)与这两个程序交互,称为兼容。
CLI(Command Line Interface ,命令行界面)
- :在计算机显示屏中,只显示字符文本,只允许用户通过键盘进行操作,例如输入一些字符串作为 shell 命令执行。
- 例:
- Linux 内核只提供了 CLI 界面,但有的 Linux 发行版也提供了 GUI 界面。
- Xterm 是一个传统的 CLI 界面,功能简单。
GUI(Graphical User Interface ,用户图形界面)
- :在计算机显示屏中,显示一些图形按钮,允许用户通过键盘、鼠标、触摸板等方式操作。
- 优点:对于不熟悉计算机的用户而言,GUI 方式最容易使用,而 CLI、API 方式都存在学习成本。
- 缺点:对于程序员而言,GUI 方式需要鼠标手动点击,不能像 CLI、API 方式那样自动化。
- 例如:很多 Linux 发行版安装了 X Window System ,简称为 X11 。然后在 X11 的基础上,运行 GNOME、KDE 等图形桌面。
比较 ABI 与 API :
- ABI 通常用于底层软件。而 API 通常用于上层软件。
- ABI 使用二进制数据,难以被人类阅读。而 API 使用字符代码,容易被人类阅读。
- ABI 接口是跨编程语言的,因为任何编程语言都能生成二进制数据。而调用 API 时,只能按少量几种编程语言编写代码。
# 系统接口
一个操作系统(Operating System)包含大量软件,分为几个大类:
- 内核(kernel)
- :操作系统的核心软件,负责实现操作系统中最基础的功能:控制计算机硬件。例如 CPU 调度、内存分配、磁盘读写。
- 内核代码与计算机硬件高度耦合。例如需要编写不同的代码,从而适配不同型号的 CPU 。
- 上层软件(high-level software)
- :泛指除了内核以外的其它所有软件。
- 上层软件不能独立运行,而是依赖内核。因为上层软件需要调用系统接口,才能间接控制计算机硬件。
- 例如一个 MP3 播放器软件,需要调用系统接口,让 CPU 执行代码,让扬声器播放音频。
- 内核是操作系统中必须运行的软件,而上层软件不是必须的。
- 如果想开发一个代码体积很小的操作系统,则可以不包含上层软件,只包含内核,甚至将内核中不重要的代码删掉。
- 底层软件(low-level software)
- :泛指一些提供基础、通用功能的软件,经常被其它软件调用、依赖,是其它软件的底层。
- 例如库函数、编译器、硬件驱动。
- 底层软件是一个相对的概念。
- 例如 MySQL 是很多软件系统中的底层软件。但相对于内核而言,MySQL 是上层软件。
- 严格而言,底层软件属于上层软件。但有时说到底层软件,也包括内核。
- 底层软件更接近计算机内核、硬件,通常以 ABI、API 方式使用,较麻烦。而上层软件更接近人类用户,通常以 CLI、GUI 方式使用,较方便。
- 内核(kernel)
操作系统的内核会提供一组系统调用接口(System Call Interface,SCI),通常为 API 的形式,供上层软件调用。
- 优点:
- 简化了开发上层软件的工作量。不需要亲自编码来控制计算机硬件,不需要了解计算机硬件的大部分细节。
- 使得上层软件的代码与计算机硬件解耦。可以将一个上层软件拷贝到不同的计算机硬件上运行,只要系统接口相同。
- 提高了系统的稳定性、安全性。因为上层软件只能执行系统接口允许的操作,不能随意控制计算机硬件。
- 缺点:
- 上层软件虽然可以调用系统接口,间接控制计算机硬件,但速度可能不如直接控制计算机硬件。
- 例如 Linux 中,上层软件每次调用系统接口时,都需要进行 CPU 上下文切换,切换执行内核程序。
- 可能导致上层软件的代码与系统接口耦合。例如一个上层软件需要调用内核的某个接口,而其它操作系统可能不存在同名接口,导致该软件不能拷贝到其它操作系统中运行。
- 上层软件虽然可以调用系统接口,间接控制计算机硬件,但速度可能不如直接控制计算机硬件。
- 优点:
例:
- Linux 内核提供了几百个系统接口。可以修改内核 C 语言源代码,增加新的系统接口。
- Linux 系统中使用 strace 命令,可打印一个进程调用的所有系统接口。
- Linux 系统接口举例:
fork() // 拷贝当前进程,创建一个子进程 write() // 写数据到文件中 brk() mmap()
# POSIX
1990 年代,为了统一不同操作系统的接口,IEEE 协会制定了 POSIX(Portable Operating System Interface of UNIX,可移植的操作系统接口)标准。
- POSIX 标准定义了一个操作系统应该提供哪些系统接口,以及每个接口应有的功能、输入、输出,但不限制每个接口的源代码怎么写。
- POSIX 标准在设计上主要借鉴了 Unix 操作系统。
- 优点:如果两个操作系统都遵循 POSIX 标准,则可以将一个操作系统中的软件,拷贝到另一个操作系统上运行。此时称这两个操作系统兼容(compatible),软件可移植(portable)。
POSIX 标准定义了大量系统接口,而一般的操作系统难以遵循 POSIX 的全部内容,只能遵循 POSIX 的基本内容。例:
- Unix 系统、类 Unix 系统基本兼容 POSIX 。
- Linux 系统基本兼容 POSIX ,因此 Linux 上的软件通常能移植到 UNIX 系统上运行。
- Windows 系统一直沿用 1993 年发布的 Windows NT 系统接口,不兼容 POSIX 。
- Darwin 系统基本兼容 POSIX 。
- Android 系统采用 Linux 内核,但底层软件与 Linux 系统的差异较大,对 POSIX 的兼容性较少。
# 库函数
开发上层软件时,有些源代码需要重复使用,因此人们将这些常用代码封装为一些库函数(library function),以 API 形式被其它上层软件调用。
- 库函数的定位:
- 相对于内核而言,库函数属于上层软件,可以调用系统接口。
- 相对于一般的上层软件而言,库函数属于底层软件。
- 一个上层软件,可以调用其它上层软件(比如库函数)来实现某种功能,也可以直接调用系统接口。
- 用户可以在一个操作系统中,安装多种库函数。通常只需下载它们的库文件。
- 优点:
- 简化了开发上层软件的工作量。
- 缺点:
- 上层软件调用库函数时,需要采用与库函数相同的编程语言。
- 库函数的定位:
例:
- Linux 系统自带了 glibc 库,提供了一些 C 语言的库函数。例如:
printf() // 在计算机终端打印一行字符串。其原理是调用系统接口 write() ,向文件描述符为 1 的文件,写入 n 个字符 malloc()
- Unix 系统上,使用 ldd 命令可查看一个程序依赖哪些库文件。例如:
[root@CentOS ~]# ldd /bin/echo linux-vdso.so.1 => (0x00007ffe3d5e7000) libc.so.6 => /lib64/libc.so.6 (0x00007fc3323e3000) /lib64/ld-linux-x86-64.so.2 (0x00007fc3327b1000)
- Windows 系统自带了一些 C 语言的库函数,但是函数源代码保密,只公开了函数名。
- Windows 系统的这些库函数,名称、用法与 Linux 库函数不同。
- Linux 系统自带了 glibc 库,提供了一些 C 语言的库函数。例如:
根据开发者的不同,可以将库函数分为两类:
- OS 库
- :操作系统自带的一些库函数。
- 优点:
- 安全。
- 功能稳定。因为被很多用户使用、反馈。
- 缺点:
- 只提供一些基础的功能,使用起来依然麻烦。
- 第三方库
- :由第三方(比如开源工作者、商业公司)开发的一些库函数。
- 优点:
- 功能丰富。
- 缺点:
- 可能包含恶意代码。
- 可能存在功能故障。
- OS 库
# GNU
:自由软件计划(GNU is Not Unix),1983 年由美国人 Richard Stallman 发起。
- GNU 旨在推广自由软件(free software)的理念。
- 他认为电子软件的一大优点就是容易拷贝,这是用户的基本自由,不能被非自由软件剥夺。
- 他希望软件开发者不是靠昂贵的版权费获利,而是靠技术支持等服务获取报酬。简单来说就是 "资源免费,服务收费" 。
- 自由软件强调自由,而不是单纯的免费。
- 计算机软件的功能、设计原理、编程语言本身没有版权,因此一款软件可以被别人反向编程。比如 Java 语言没有版权,但甲骨文公司拥有 JVM 和一些类库的版权。
- 1985 年他创建了自由软件基金会(Free Software Foundation ,FSF),作为 GNU 计划的主要赞助组织。
- GNU 计划的目标是创建一个完全自由的操作系统,从里到外使用的软件都是自由软件。
- GNU 计划已经开发了很多流行的自由软件,例如 glibc、gcc、make、bash 。
- GNU 计划最初打算为这个操作系统开发一个内核,称为 hurd ,但一直没有完成。后来改用 Linux 内核。
# GPL
:GNU 通用公共许可证(GNU General Public License),是 GNU 运动推广的一种开放授权的版权协议。
- 1989 年发布 v1 版本,允许 GNU 软件可以被所有人自由地使用、复制、修改和再发布,任何人都不能限制该权利。
- 1991 年发布 v2 版本,对程序库的许可宽松一些。
- 2007 年发布 v3 版本,修补了一些法律漏洞。
# 开源
1998 年,自由软件阵营中的部分成员分裂出来,以 "开源" 的名义开展活动。
- 开源是指对外公布软件的源代码,但不一定允许其他人使用、修改源代码,因此开源软件不一定是自由软件。
- 很多公司利用开源的方式,吸引社区开发者免费贡献,提高软件质量。
# ASF
:Apache 软件基金会(Apache Software Foundation)
- 于 1999 年由 Apache HTTP 服务器的开发者们创立 ,目前已成为世界上最大的开源基金会,管理的开源软件越来越多。
- 其他个人或团体可以将项目捐赠给 ASF 管理、维护,这需要放弃自己对该项目及其商标的所有权。
- 捐赠的项目需要先进入 Apache 孵化器(Incubator),通过一些质量审核、投票之后才可以毕业,正式成为 Apache 顶级项目,或者其它项目的子项目。
- ASF 项目列表 (opens new window)