前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >现代操作系统最核心抽象之一 —— 文件

现代操作系统最核心抽象之一 —— 文件

作者头像
木鸟杂记
发布2024-01-24 17:24:57
1150
发布2024-01-24 17:24:57
举报
文章被收录于专栏:木鸟杂记木鸟杂记

我们对文件(File)如此熟悉,以至于很少去思考其本质和关联的一些概念。本文参考 XV6 小册[1]将会简单梳理下文件抽象的本质、妙处和一些细节。

本质

说到文件,用惯了图形化操作系统的我们,第一反应是:文件夹中的一个个图标。但现代操作系统鼻祖 —— Unix 最初设计“文件”时,对其定义远不止于此。即使在今天的 Linux、MacOS 、Windows 的应用开发者眼里,文件的范围也要更大的多。

这也是软件世界最常见的迷思之一——普通用户眼里的形形色色的图标,在系统程序员眼里都是流动的数据。普通用户眼中的操作系统其实是程序员常说的 GUI[2](Graphic User Interface,用户图形界面) ,也即一个表面层。依靠进程(Process)、文件(File)、管道(Pipe)等核心抽象构建的各种系统调用和周边工具,才是真正的向下管理硬件、向上封装接口的操作系统。它是由一段段数据和一个个控制有机组合而成的。

这里借用超棒科幻片 The Matrix[3] (黑客帝国)一幕名场景,来助大家体会下这种感觉:

黑客帝国名场面

值得一提的是,在时下大火的 AI 背后的深度学习,也是基于矩阵的( Matrix-Based)。此外,笔者从事过的领域——图数据库的老大 Neo4j,以及其开源的最流行的图查询语言——OpenCypher,得名灵感都来自于本系列电影(Neo 就是主角,Cypher 是第一集中的叛徒)。之前在面试 Neo4j 的时候,还和他们的 talent acquisition 求证过这一点。

不得不说,这个拍于 1999 年的电影系列,用一幕幕精彩的场景堆砌出的各种隐喻和明喻,都十分精准和超前。这是唯一一个我看了超过三遍的系列。

回到正题,在 Unix 设计中,文件的本质是什么?答曰——字节流

因此,操作系统中的“文件”远不止存在于外存(磁盘或 SSD)那些各种格式的文件,任何 IO 设备(网络通信、外设设备)、管道,甚至内存本身,都可以作为文件被进程打开——因为他们都可以被当做字节流。正是这种抓住本质的抽象,使得操作系统长我们今天看到的这样——其他过于复杂的抽象和实现都淹没在了历史长河中。

妙处

那么,使用字节流来作为文件的抽象有何妙处呢?答案是软件工程中提到的最多的一个词——解耦。有了这种抽象,进程(对 CPU 运算能力的抽象)就无需关心各种设备和组件底层细节。这会极大简化各种系统程序和应用程序对硬件的使用方式。

在这种“万法归一”的抽象基础上,还有一个很重要的伴生抽象——“管道”(Pipe)。如果说文件是对单个对象的抽象,那么管道就是连接不同对象的关键。没有管道,文件顶多是“字节集”;有了管道,文件才可以流动,成为真正的“字节流”。

数据作为软件中的基本元素,在流动的过程中,被不同的程序锻打、组合,最后套一个表面层,成为一个个可以被普通用户使用的网页、APP 和桌面软件。这背后,都离不开文件和管道。

细节

说完了感性部分,让我们来看下文件接口细节。通常来说,文件是可以被多个进程共享的,因此在软件的基础上,我们进一步抽象出:文件描述符(file descriptor,缩写 fd)。它其实是对文件的一个视图,包含一个文件指向和一个偏移量。其中偏移量是隐式维护的。

Kafka 在对 Topic 进行抽象的时候,也是用的类似的方式—— Consumer 会维护一个关联到 Topic 的偏移量。从这个侧面也可以看出文件的抽象是多么成功。实际上,后来很多数据系统的接口都有它的影子。

文件描述符是一个进程范围的整数。且我们固定 0 是标准输入,1 是标准输出。这样就可以通过管道来将数据流进行重定向,从而对不同的“处理过程”进行自由组合:

  1. 每个处理过程(cmd 工具)都只管专注一小件事。
  2. 需要输入就从标准输入读取;需要输出,就输出到标准输出。
  3. 管道负责将一个个小工具串成一个复杂的处理过程。

这就是大名鼎鼎的 KISS[4] (keep it simple,stupid)原则,也是我们日常生活中拆解复杂任务[5]的一种惯常手段,也是现在常见的数据流工具 (Spark,Flink)的背后原理。

围绕文件描述符,我们有几大文件操作语义:

  1. open:以某种模式打开文件,会返回一个文件描述符,并隐式的初始化该 fd 的 offset = 0 。
  2. read(fd, buf, n) :从文件描述符 fd 关联的文件和偏移量处读取最多 n 个字节到 buf 中;读取成功后,会前移 fd 关联的偏移量(因此调用者就可以用一个循环来连续读取,而不用自己维护偏移量),且返回实际读到的字节数;如果读取失败则返回值小于 0。
  3. write(fd, buf, n) :从 buf 中写入 n 个字节到文件描述符 fd 关联的文件和偏移量处;并且会自动前移 fd 相应字节的偏移量。写入成功,返回 n;写入失败,则返回值会小于 n。
  4. close(fd) :释放 fd 和所占资源(比如文件指针和偏移量等信息),且进程之后就可以复用该 fd 标号。

有了这几个基本的接口,进程就可以对文件的字节流进行管理和读写。

最后,实现和承载文件这一抽象的系统,我们通常称为文件系统。当然,这又是另外一个经典的话题。用关系数据库来类比,文件的抽象类似关系模型,open-read—close 类似 SQL,而文件系统就是类似 DBMS 的那个实现系统。

如果大家对这个话题感兴趣可以留言,我可以之后再专门写文章来聊文件系统。

参考资料

[1]

6.S081 参考书 XV6: https://pdos.csail.mit.edu/6.828/2020/xv6/book-riscv-rev1.pdf

[2]

GUI: https://en.wikipedia.org/wiki/Graphical_user_interface

[3]

黑客帝国名场面: https://movie.douban.com/subject/1291843/

[4]

KISS: https://en.wikipedia.org/wiki/KISS_principle

[5]

拆解复杂任务: https://www.qtmuniao.com/2023/08/21/life-engineering-many-passes

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 木鸟杂记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本质
  • 妙处
  • 细节
    • 参考资料
    相关产品与服务
    图数据库 KonisGraph
    图数据库 KonisGraph(TencentDB for KonisGraph)是一种云端图数据库服务,基于腾讯在海量图数据上的实践经验,提供一站式海量图数据存储、管理、实时查询、计算、可视化分析能力;KonisGraph 支持属性图模型和 TinkerPop Gremlin 查询语言,能够帮助用户快速完成对图数据的建模、查询和可视化分析。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档