写时复制如何与 mmap 函数中的只读虚拟页配合使用?

写时复制如何与 mmap 函数中的只读虚拟页配合使用?

我是C和Linux新手,只是一个关于函数使用的问题mmap,函数原型mmap

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

我看到这样的代码:

char *srcp = mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);

我们知道这PROT_READ意味着虚拟页面只能读取。并MAP_PRIVATE表明它是一个私有的写时复制对象。写时复制技术就像是,当两个进程使用同一个对象时,当进程A修改该对象时,这些更改仅属于进程A,而对进程B不可见。因此MAP_PRIVATE允许用户写某物,但PROT_READ表示只读,因为我们只能读取它,所以没有意义使用COW(要使用COW,你需要能够先写一些东西,然后COW将使更改仅对你的进程可见),它们不是相互矛盾的吗?

答案1

调用时mmap,调用者必须在共享 ( MAP_SHARED) 或私有 ( MAP_PRIVATE) 映射之间进行选择。使用写时复制是一个实现细节;与之比较POSIX 定义mmap

映射的类型(共享或私有)仅决定写入时发生的情况。因此,对于PROT_READ,这并不重要,并且使用写时复制也没有关系。对支持文件所做的任何更改最终都将在进程的映射中可见,即使使用私有映射也是如此。理论上,这种行为可能会改变:

映射的更新对于映射同一文件的其他进程来说是不可见的,并且不会传递到底层文件。未指定调用后对文件所做的更改是否mmap()在映射区域中可见。

(从MAP_PRIVATE中的描述man 2 mmap)。

另请注意,进程可以使用以下命令更改内存保护mprotect,假设它能够写入底层文件。映射类型无法更改,但保护可以,因此进程可以将文件映射为只读,然后更改为读写(如果文件本身以读写方式打开);那么写时复制就变得重要了。

(谢谢用户414777用于纠正此答案之前版本中的一些错误。任何剩余的错误都是我自己造成的。)

相关内容