java - 当我读/写文件时发生了什么(在操作系统级别)?

标签 java file programming-languages filesystems operating-system

假设一个程序正在读取文件 F.txt,同时另一个程序正在写入该文件。

(当我考虑如果我是一名系统程序员我将如何实现这个功能时)我意识到在以下方面可能存在歧义:

  1. 第一个程序会看到什么?

  2. 第二个程序在哪里写入新字节? (即“就地”写入 vs 写入新文件,然后用新文件替换旧文件)

  3. 有多少个程序可以同时写入同一个文件?

    .. 也许还有一些不那么明显的东西。

所以,我的问题是:

  1. 读/写文件功能的主要策略是什么?

  2. 哪些操作系统(Windows、Linux、Mac 操作系统等)支持它们中的哪些?

  3. 是否可以依赖某种编程语言? (我可以假设 Java 可以尝试在所有支持的操作系统上提供一些统一的行为)

最佳答案

从磁板/闪存单元到您的本地 Java 变量,单字节读取有很长的路要走。这是单个字节传播的路径:

  1. 磁板/闪光电池
  2. 内部硬盘缓冲区
  3. SATA/IDE 总线
  4. SATA/IDE 缓冲器
  5. PCI/PCI-X总线
  6. 计算机的数据总线
  7. 计算机的 RAM 通过 DMA
  8. 操作系统 Page-cache
  9. Libc 读取缓冲区,又名用户空间 fopen() 读取缓冲区
  10. 本地 Java 变量

出于性能原因,操作系统完成的大部分文件缓冲都保留在页面缓存中,将最近读取和写入的文件内容存储在 RAM 中。

这意味着您的 Java 代码中的每个读写操作都是从您的本地缓冲区完成的:

FileInputStream fis = new FileInputStream("/home/vz0/F.txt");

// This byte comes from the user space buffer.
int oneByte = fis.read();

页面通常是一 block 4KB 的内存。每个页面都有一些特殊的标志和属性,其中之一是“脏页”,这意味着该页面有一些未写入物理介质的修改数据。

一段时间后,当操作系统决定将脏数据刷新回磁盘时,它会以与数据来源相反的方向发送数据。

每当两个不同的进程将数据写入同一个文件时,产生的行为是:

  • 不可能,如果文件被锁定。第二个进程将无法打开该文件。
  • 未定义,如果写入文件的同一区域。
  • 预期,如果操作文件的不同区域。

“区域”取决于您的应用程序使用的内部缓冲区大小。例如,在一个两兆字节的文件上,两个不同的进程可能会写入:

  • 第一个 1kB 数据 (0; 1024)。
  • 另一个关于最后1kB的数据(2096128;2097152)

只有当本地缓冲区的大小为 2 兆字节时,才会发生缓冲区重叠和数据损坏。在 Java 上,您可以使用 Channel IO通过细粒度控制内部情况来读取文件。

许多事务性数据库通过发出 sync operation 强制将本地 RAM 缓冲区中的一些写入返回到磁盘.与单个文件相关的所有数据都被刷新回磁板或闪存单元,有效确保断电时不会丢失任何数据。

最后,一个 memory mapped file是一个内存区域,它使用户进程能够绕过用户空间缓冲直接读取和写入页面缓存。

页面缓存系统对于多任务处理的性能至关重要 protected mode OS 和每个现代操作系统(Windows NT 以上版本、Linux、MacOS、*BSD)都支持所有这些功能。

关于java - 当我读/写文件时发生了什么(在操作系统级别)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4869368/

相关文章:

java - selenium 和 java 的范围报告 - 如何在屏幕/控制台上查看测试进度

java - Matlab 矩阵到 Java 列表的快速转换

programming-languages - 编程语言中的术语 'object' 和 'instance' 之间有什么区别?

programming-languages - 学习计算机和编程

programming-languages - 为什么 Verilog 不被视为编程语言?

java - 如何在多个类之间传递对象? java

java - 在Java中放心测试特定方法

Java fileinputstream 读取而不使用 .read()

c# - 强制打开一个文件

file - 在Powershell脚本中将文件从一个位置复制到另一位置,此外还要检查某些值