⚙️ 第七章 程序在怎样的环境下运行
📄 一句话概括

API 就是操作系统提供的整套功能;各家接口的名字、参数、行为都不一样,同一个功能得写好几套代码。

📝 本节和前面几节的关系

7.2 看了操作系统能吸收什么,这一节看它自己带来的差异。

一、API 是什么

写程序时你调用的那些功能——打开文件、创建进程、分配内存——都不是语言自带的,而是操作系统给的。 这套功能合起来就叫 API(应用程序接口)。 程序能不能跑,取决于那台机器上有没有它要调的那些 API。 所以【应用】这个词很准确:程序是站在操作系统这个地基上的。

二、各家为什么不一样

Windows 和类 Unix 系统是各自独立发展起来的,接口的命名、参数、行为都不一样。 打开一个文件,一边叫 CreateFile,另一边叫 open;创建进程更是一个用 CreateProcess、另一边用 fork 加 exec。 连换行符这种小事都不一样:一边是回车加换行两个字符,另一边只有一个。 这些差异没有谁对谁错,纯粹是历史积累的结果。

三、于是程序要写好几套

如果直接用系统 API,同一个功能就得为每个系统各写一份。 这对开发者是最头疼的事:改一处逻辑,要在多个版本里各改一遍。 高级编程语言的解法是再包一层:把各家不同的接口包成一套统一的写法。 所以你在 Python 里写 os.path.join,它在两个系统上拼出来的路径其实不一样——但你不必操心。

四、包一层也带来了新的问题

包得越厚,越跑不快。 一层层转发是有开销的。 包得越厚,越用不上平台独有的好东西。 统一接口只能取各家功能的交集。 包得越厚,兼容越难。 换个语言版本,包本身可能就变了。 这三条权衡在整本书里反复出现:抽象带来方便,也带来代价(第九章还会细讲)。

五、动手 Demo:每种操作系统的API都是不同的

API 就是操作系统提供的那一整套功能。 麻烦在于:各家提供的接口名字、参数、行为都不一样。

import os
print("os.name      ", os.name)
print("路径分隔符    ", repr(os.sep))
print("换行符        ", repr(os.linesep))
print("拼一个路径    ", os.path.join("data", "a.txt"))

实跑输出:

--------------------------------------------------------------------
每种操作系统的API都是不同的
--------------------------------------------------------------------

**API=应用程序接口**,也就是操作系统提供的那一整套功能。
写程序时调用的文件、网络、进程接口,**都是操作系统给的。**

  麻烦就在这儿:**各家提供的接口名字、参数、行为都不一样。**

  要做的事         Windows 一套      类 Unix 一套
  --------------------------------------------------
  打开文件         CreateFile        open
  读文件           ReadFile          read
  创建进程         CreateProcess     fork/exec
  创建线程         CreateThread      pthread_create
  获取当前时间     GetSystemTime     gettimeofday

  所以**同一个功能,代码要写两套、甚至好几套。**
  高级编程语言的做法是**包一层**:把各家不同的接口**包成一套统一的写法**(这就是第九章的抽象化)。

  实测一下 Python 替我们垫的那层:

    os.name           nt
    路径分隔符        '\\'
    换行符            '\r\n'
    平台特有的模块    nt(仅 Windows)或 posix(仅类 Unix)

  **同一行 `os.path.join` 在两个系统上拼出来的路径都不一样——**
  正因为如此,**跨平台的程序得处处小心这些差异。**

同一行 os.path.join,在两个系统上拼出来的路径就不一样。 高级语言替我们垫了一层,把各家不同的 API 包成了统一的写法。

30 秒实验

  1. 在 Windows 上打印 os.sep,再想它在 Linux 上会是什么。
  2. 找一个用了平台特有功能的 Python 库,看看它是怎么处理跨平台的。

常见误区

  1. 以为语言自带了开文件的功能。那是操作系统提供的 API。
  2. 以为跨平台是免费的。包一层会带来性能与兼容上的代价。
自测三问(点开对答案) 1. API 指的是什么? —— 操作系统提供给应用程序调用的一整套功能接口。 2. 各家操作系统的 API 有什么不同? —— 名字、参数、行为都不一样,比如打开文件一边叫 CreateFile、一边叫 open。 3. 高级语言怎么处理这些差异? —— 把各家的接口包成一层统一的写法,代价是性能和平台特有功能上的损失。

相关笔记