您似乎将内存映射与驻留在内存的文件系统中的文件以及其他概念(例如,进程在移动时如何保持对文件的访问权)相混淆。
我将一个问题一个问题地问我是否可以解决问题。
- 假设我浏览到文件系统中的目录,并且该目录中有一个文件。该文件是否可能指向主内存中的区域,而不是指向磁盘中的区域?
如果它位于驻留内存的文件系统上,则它确实指向主内存,例如通常安装在/ proc上的procfs或/ sys上的sysfs或有时在/ tmp上的tmpfs。
- 如果可能的话,这就是我们所谓的“内存映射文件”吗?
不会。就像stephen-kitt所说的那样,“内存映射”是一种通过在主内存上“映射”文件并在其中使用文件来访问文件的方法,而不是通过read()和写()。
- 在文件系统中移动此类文件(即,将此类文件从目录移动到另一个目录)的含义是什么?我了解的是,由于文件是内存映射的,因此与文件交互的进程始终写入主内存的预定义区域,并且当我们打开该文件(例如,使用vim)时,我们会读取该区域。主内存(因此,不涉及磁盘)。因此,无论我们将文件移到何处,它都将始终正确运行,对吗?如果是,在文件系统中移动文件是否有意义?
如果在同一个文件系统中移动它,实际上就是在一个引用(从一个目录到另一个目录的索引节点)中移动。如果已经打开了该文件的程序,则它们仍将访问同一文件,因为它们已经通过文件描述符准备好了索引节点。这就是您在注释中提到的table_name.idb文件所发生的情况。
- 是否有一条命令可以判断文件是否已映射内存?
Wossname已针对内存映射文件回答了此问题。lsof
会告诉您哪些进程具有文件内存映射。
要知道文件是否在驻留内存的文件系统中,可以使用df
或
mount
列出文件系统及其挂载点。您只需要通过查找即可知道哪种类型的文件系统驻留在内存中(例如,在Wikipedia中)。
- 最后,如果我用vim打开一个内存映射文件,对其进行一些更改并保存并关闭vim,会发生什么?我所做的更改是否只会写入主存储器?如果是这样,使用此文件的其他进程会看到我刚刚所做的更改吗?以我的经验,当我使用vim对文件进行一些更改时,其他进程没有看到我对该文件所做的更改。这是什么原因呢?
就我个人而言,我还没有mmap
在C程序中使用过该函数,但是据我从略读man mmap
和了解到info mmap
,在保持内存中的表示同步方面并没有任何魔术。调用mmap的基本形式是将文件内容复制到内存,msync
并用于将其从内存写回到磁盘。如果磁盘文件发生更改,则没有任何位置可以检测到该文件并自动在映射该文件的所有进程中修改内存中的表示形式。
编辑:事实证明,在某些情况下,mmap()实际上确实尝试使内存中的表示形式保持同步。如果仅从读取映射,则即使其他进程写入文件,也将保持同步。如果将其写入(通过分配给内存区域),则发生的情况取决于向mmap()提供了哪些表面上必需的MAP_SHARED或MAP_PRIVATE标志。如果提供了MAP_PRIVATE,则映射从磁盘上的表示派生,并停止同步,直到您使用msync()为止。如果提供了MAP_SHARED,则更新将对其他已映射文件的进程以及磁盘上的表示形式可见(尽管这不一定是立即的)。
我只是在一个现有文件上打开vim e
,然后在另一个终端:w
上inotifywait -m .
运行时运行命令。在一些奇怪的地方中,这是我从中获得的重要部分inotifywait
。
./ MOVED_FROM e
./ MOVED_TO e~
./ CREATE e
./ OPEN e
./ MODIFY e
./ CLOSE_WRITE,CLOSE e
./ ATTRIB e
./ ATTRIB e
./ DELETE e~
Vim创建一个新文件,并删除旧文件。为什么这样做而不是修改文件超出了此问题的范围,但是重点是这是一个新文件,因此具有新的inode。
现在,使用此文件的其他进程对您意味着什么?如果您是指在执行此操作的同时打开了文件的进程,则不会,他们将看不到更改。这是因为,尽管他们打开了具有相同路径的文件,但它们不是同一文件。如果您指的是执行此操作后可能会打开文件的进程,那么可以,他们将看到更改。他们将打开您创建的新文件。
需要注意的重要一点是,尽管程序似乎在用户界面上打开了文件,但这并不一定意味着它们在此过程中保持文件打开。如上所示,Vim就是一个例子。