inode->i_rwsem 和 i_flctx 有什么不同?

inode->i_rwsem 和 i_flctx 有什么不同?

当我在调用时跟踪函数图时write(),我发现在函数内ext4_file_write_iter()它在开始时inode->i_rwsem通过调用锁定了。inode_lock(inode)之后调用__generic_file_write_iter()将数据写入文件。并inode最终解锁。

那么它是inode->i_rwsem用来保护对同一文件的并发写入吗?

但是我编写了一个程序,该程序同时将数据写入文件的同一区域(pwrite(fd,buf,SIZE,0)),结果显示写入未序列化。我发现它必须使用flock/fcntl来序列化并发写入,这取决于inode->i_flctx.

我想问的是,这样做的目的是什么inode->i_rwsem

inode->i_rwseminode->i_flctx和之间有什么不同inode->i_lock

谢谢。

答案1

inode->i_rwsem由内核内部使用,以确保内核本身不会同时从文件读取或写入文件,以避免任何损坏或竞争条件。它不影响用户空间;您仍然可以同时由多个进程打开该文件以进行读/写。但是,如果多个进程尝试同时读取/写入文件,内核实际上会在幕后串行执行此操作。

在您的情况下,如果有两个进程尝试使用 写入同一区域pwrite(fd,buf,SIZE,0),而没有内部锁定机制(例如i_rwsem用于什么),则内核可能会开始从第一个进程写入一些数据,并且同时时间从第二个进程开始写入数据,没有写操作第一的过程完成。它会影响整个文件系统的完整性,甚至可能导致内核崩溃竞争条件

内核中的内部锁定可以防止这些情况发生。第一个进程的第一次写入将完成,然后才会执行第二次写入(如果它们都写入文件中完全相同的区域,则可能会覆盖第一个进程的“写入”)。

inode->i_flctx正如您已经发现的那样,当进程本身想要限制可以同时打开文件的进程数量时,它是由来自用户空间的flock/调用控制的。fcntl例如,一个进程可以锁定文件以进行写入,如果另一个进程想要在另一个进程释放同一文件之前锁定该文件,它将被拒绝或阻止。

让我们以两个进程写入同一文件并执行不同写入的情况为例。每个进程都可以覆盖其他进程写入的数据。为了避免在用户空间, 这应用程序本身可以使用flock/fcntl来防止两个进程打开同一个文件。

这是另一个例子:

  • 一个进程写入文件,第二个进程读取同一文件。
  • 第二个进程可以读取部分数据,因为第一个进程尚未完成写入。

在这种情况下,为了防止出现这种情况:

  1. 第一个进程必须获取文件的锁,以防止其他进程在完成写入之前打开该文件。
  2. 第二个进程将尝试获取同一文件的锁,并且将被阻止(或失败,取决于它尝试锁定文件的方式),因为它已经被另一个进程锁定。
  3. 第一个进程完成写入,释放锁(同样,显式地在用户空间通过调用提到的系统调用之一)
  4. 只有这样第二个进程才能锁定文件以进行读取。
  5. 当第二个进程正在读取文件时,尝试获取该文件锁的其他进程将再次被阻止,直到:
  6. 阅读过程完成阅读。

所以用flock/fcntl你可以处理这些情况以编程方式在应用程序的源代码中,内核用于i_flctx了解某个进程是否获取了文件的锁,并防止其他进程获取另一个锁,直到第一个进程释放它。

inode->i_lock,就像 一样inode->i_rwsem,仅由内核用来在处理内核中的 inode 状态时保护内核免受竞争条件的影响。i_rwsem用于保护写入,i_lock用于保护inode状态的改变。

换句话说,除非你是内核开发人员,否则你不应该担心inode->i_lockor inode->i_rwsem,它们只是内核 inode 实现机制的一部分,也不用担心inode->i_flctx哪一个是内核从用户空间锁定文件的内部实现机制的一部分。

相关内容