# 相关概念

# 操作系统

  • 使用计算机有两大条件:

    1. 准备一套计算机硬件,至少包括 CPU、内存,通常还包括硬盘、显示器、键盘等设备。
    2. 在内存中写入一套操作系统的代码,由 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 平板的专用系统。
  • 关于应用程序:
    • 安装包的扩展名:
      • .dmg :一种压缩文件格式,类似于 .iso ,
      • .pkg :一种安装包格式。
    • 包管理工具:
      • Mac App Store
      • Homebrew :提供了命令行工具 brew 。
    • 开发语言:
      • Objective-C
        • 一种编译型语言,在 ANSI C 的基础上增加了 Smalltalk 语言的特性,支持面向对象编程。
        • 于 1983 年由美国人 Brad Cox 发明。
      • C++
        • 可以基于 Qt 开发程序。
      • Swift
        • 于 2014 年由 Apple 公司发布,目标为取代 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 的首选开发语言。

# 接口

  • 开发一个软件程序,应该对外提供一些接口(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 方式使用,较方便。
  • 操作系统的内核会提供一组系统调用接口(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 库函数不同。
  • 根据开发者的不同,可以将库函数分为两类:

    • 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)