【发布时间】:2013-12-20 08:18:39
【问题描述】:
虽然这是一个一般性问题,但欢迎针对任何 Windows 或 Linux 或 Mac 支持的文件系统提供具体答案。
文件系统如何防止 2 个或更多进程同时读/写访问本地驱动器的扇区?
我知道显然需要采用某种类型的扇区锁定,但是...
-
这个操作系统范围的扇区锁的“类型”是什么:
a) 命名互斥/命名信号量/文件映射? (在 Windows 上)
b) 共享内存? (在 Linux 上)
-
这个扇区锁保存在哪里:在内存中?在磁盘上?无论哪种情况,无论此锁存储在何处,我都知道...
a) 锁的存储必须是逻辑上的临时存储,因为如果它的所有者进程崩溃,锁不应永久或无限期地悬空。因此,如果这些锁存在于内存中会有所帮助。
b) 锁的下落必须由所有进程通过名称或 ID 公开发现,该名称或 ID 找到了扇区号的函数。因此,如果进程 A 需要锁定扇区 S,A 应该知道如何首先访问扇区 S 的锁 L(S),如果 L(S) 尚不存在,则创建 L(S),尝试锁定 L(S),并且要么返回要么阻塞——所有这些都是原子的,因为另一个进程 B 也可能与 A 一起竞争,试图执行相同的步骤序列。
对于大型存储设备,扇区数也会很大。因此,显然不能在内存或磁盘上预先分配每个扇区的锁。
然而,我不知道或不理解的是,Linux 上的 ext* 文件系统、Windows 上的 FAT* 和 NTFS 以及 Mac 上的文件系统如何处理这个问题。
我的问题的实际上下文: 最终,我必须将上述答案应用于我正在使用 Java 7 NIO2 FileSystemProvider 编写的基于 Java 的自定义文件系统,其中 2 个或更多独立 Java 进程可能正在访问连接驱动器的一堆扇区以进行读/写。在 Java 7 中,我所知道的在进程之间实现共享内存的唯一非 JNI 方法是通过 MappedByteBuffer。但问题是,这个字节缓冲区将是“原始”内存——而我需要的是一个操作系统范围的互斥体类型机制,并且每个扇区 S 也可能每个互斥体。看来,我对这个 MappedByteBuffer 的更改除非我也调用MappedByteBuffer.force,否则不会在操作系统范围内以原子方式执行。
非常感谢所有答案和 cmets。
【问题讨论】:
-
是什么让您认为文件系统实现了扇区锁定? “扇区锁定”到底是什么意思?
-
如果扇区是一个共享资源,2个以上的进程可以同时读取/写入,那么这个资源,就像其他资源一样,在并发编程中需要序列化访问。这就是我所说的“扇区锁定”。但即使是你简短的反问题(你的措辞方式)也足以发人深省,所以没有冒犯,只是谢谢!
-
Harry,文件系统操作发生在驱动程序的内核模式下。驱动程序使用同步原语同步其线程,但不需要扇区锁定。
-
感谢 Eugene,但是对于 Java 程序来说,内核驱动程序等价物是什么?大声地想知道,为什么 Java 的设计者没有考虑提供一个明确的“VM 驱动程序”工具,让所有 JVM 实例通用的代码都可以运行。
-
在某些时候所有的 I/O 都变成了串行的。您似乎担心同时发生对同一扇区的两次写入。这不可能发生,因为硬件一次只能执行一项操作。所以问题是:我们如何防止多个进程同时访问同一个硬件?或者,它与一些“更高”级别的碰撞有关。并非所有文件系统都提供这种更高级别的预防。文件系统不需要防止下层冲突,就是驱动的问题。
标签: java filesystems locking shared-memory