为什么在 Unix 文件系统设计中存在open()
并存在?close()
操作系统不能只检测第一次read()
或被write()
调用并执行open()
通常会执行的操作吗?
答案1
丹尼斯·里奇在中提到«Unix 分时系统的演变»thatopen
以及close
、和从一开始read
就存在于系统中。write
creat
我想一个没有 和 的系统open
并不是close
不可想象的,但我相信这会使设计变得复杂。您通常希望进行多次读写调用,而不仅仅是一次,对于 UNIX 起源于 RAM 非常有限的旧计算机来说尤其如此。拥有一个维护当前文件位置的句柄可以简化此操作。如果read
或write
要返回句柄,他们必须返回一对——句柄和他们自己的返回状态。该对的句柄部分对于所有其他调用都是无用的,这将使这种安排变得尴尬。将游标的状态留给内核使其不仅可以通过缓冲来提高效率。还有一些与路径查找相关的成本——拥有句柄让您只需支付一次。此外,UNIX 世界观中的某些文件甚至没有文件系统路径(或者没有——现在它们有诸如 之类的东西/proc/self/fd
)。
答案2
然后所有的read
和write
调用都必须在每个操作上传递此信息:
- 文件名
- 文件的权限
- 调用者是否正在追加或创建
- 呼叫者是否是完毕处理文件(丢弃未使用的读缓冲区并确保写缓冲区真正完成写入)
无论你考虑独立来电 open
、read
、write
和close
比单一用途 I/O 更简单信息基于您的设计理念。 Unix 开发人员选择使用可以通过多种方式组合的简单操作和程序,而不是单一操作(或程序)来完成所有操作。
答案3
文件句柄的概念很重要,因为 UNIX 的设计选择是“一切都是文件”,包括不属于文件系统的部分。例如磁带驱动器、键盘和屏幕(或电传打字机!)、穿孔卡/磁带阅读器、串行连接、网络连接以及(UNIX 的关键发明)与称为“管道”的其他程序的直接连接。
如果您查看许多简单的标准 UNIX 实用程序(例如 )grep
,尤其是它们的原始版本,您会注意到它们不包含对open()
和 的调用,close()
而只包含read
和write
。文件句柄已设置外部程序由 shell 执行并在启动时传入。因此程序不必关心它是写入文件还是另一个程序。
除了 之外open
,获取文件描述符的其他方法还有socket
、listen
、pipe
、dup
以及通过管道发送文件描述符的非常 Heath Robinson 机制:https://stackoverflow.com/questions/28003921/sending-file-descriptor-by-linux-socket
编辑:一些讲义描述间接层以及这如何让 O_APPEND 合理地工作。请注意,将 inode 数据保留在内存中可以保证系统不必在下一次写入操作时再次获取它们。
答案4
Open() 提供了一种在文件使用时锁定文件的方法。如果操作系统自动打开、读取/写入文件,然后再次关闭文件,则无法阻止其他应用程序在操作之间更改这些文件。
虽然这可以管理(许多系统支持非独占文件访问),但为了简单起见,大多数应用程序假设它们打开的文件不会更改。