⚙️ 第九章 操作系统与应用程序的关系
📄 一句话概括

平时几乎感觉不到操作系统,但几乎每一步都要经过它:打开文件、申请内存、打印一行字、启动另一个程序。

📝 本节和前面几节的关系

9.1 讲了它怎么来的,这一节把镜头对准【它此刻正在替你做什么】。

一、你写的每一句,几乎都落在它身上

打开一个文件——它去查目录、叫驱动去读磁盘。 申请一块内存——它分配物理页、改页表。 往屏幕打印一行字——它把字符交给显卡或控制台。 启动另一个程序——它创建进程、把代码加载进去。 感觉上这些都是【语言的功能】,实际上全是操作系统在干活。

二、看不见,是因为它包得好

为什么你平时完全感觉不到?因为它把自己藏在了两层封装底下。 最上面是语言提供的写法(读文件、打印),再往下是系统调用,最底下才是硬件。 语言把系统调用包起来,于是你写的东西看起来跟操作系统毫无关系。 这也是抽象化的好处:用起来方便。代价是——出了问题你往往不知道该往哪一层看。

三、对比两种写法,就看出了层

用两种写法打开同一个文件,拿回来的东西完全不一样: open(...) 给你一个带缓冲的文件对象——这是语言替你加的。 os.open(...) 给你一个整数文件句柄——这几乎就是系统调用本身。 层层往下,每一层都在替你做一点事,也都在遮住一点东西。 所以【调不动】的时候要会往下看:把高层写法换成低层写法,往往就能看清卡在哪儿。

四、为什么值得知道它存在

三个实际好处: 排错时更快。 报错信息里的【权限不足】【文件被占用】,说的都是操作系统的事。 性能上更好判断。 一次操作是【动内存】还是【碰磁盘】,差着好几个数量级。 跨平台时不吃瘪。 知道哪一层是系统相关的,就知道哪里可能出问题。 一句话:它虽然不在你的代码里,但它在你的代码下面。

五、动手 Demo:关注操作系统的存在

平时写程序几乎感觉不到操作系统,但它几乎什么都替你干了。 用两种写法打开同一个文件,就能看出【包了几层】。

import os
f = open("_u27.py", "rb")
fd = os.open("_u27.py", os.O_RDONLY)
print("open(...)   ->", type(f).__name__)
print("os.open(...) ->", type(fd).__name__)
f.close(); os.close(fd)

实跑输出:

--------------------------------------------------------------------
关注操作系统的存在
--------------------------------------------------------------------

平时写程序几乎感觉不到操作系统,**但它几乎什么都替你干了。**

  程序以为自己在做的事     实际是谁在做
  --------------------------------------------------------
  打开一个文件             系统去查目录,驱动去读磁盘
  申请一块内存             系统分配物理页、改页表
  往屏幕打印一行字         系统把字符交给显卡或控制台
  启动另一个程序           系统创建进程、把代码加载进去
  看键盘有没有按下         系统收集设备中断,再分发给程序

  用两种写法打开同一个文件,就能看出【包了几层】:

  写法             拿到的是            谁在处理
  -----------------------------------------------------------
  open(...)        BufferedReader      Python 又包了一层缓冲
  os.open(...)     int(文件句柄)     几乎就是系统调用本身

  **所以【程序的每一步】几乎都要经过操作系统。**
  它不在你的代码里,**但它在你的代码下面。**

实测:open 给出 BufferedReader(语言又包了一层缓冲);os.open 给出一个 int 文件句柄。 越往下越接近系统调用,也越难用、越看得清真相。

30 秒实验

  1. 把程序里的一处 open 换成 os.open 走一遍,感受一下多出来的手工活。
  2. 想一想:为什么删一个正在被打开的文件,有时会失败。

常见误区

  1. 以为读文件是语言自带的功能。那是操作系统提供的。
  2. 以为层数越少越好。高层写法更安全、更省事,只是遮住了细节。
自测三问(点开对答案) 1. 打开文件这件事实际是谁在做? —— 操作系统:查目录、让驱动去读磁盘;语言只是提供了一层写法。 2. open 和 os.open 有什么不同? —— open 返回带缓冲的文件对象(语言再包一层);os.open 返回整数文件句柄,几乎就是系统调用本身。 3. 知道操作系统存在有什么用? —— 排错更快、判断性能有依据、跨平台时知道哪里可能出问题。

相关笔记