c - 我有一个关于虚拟内存的问题,它实际上包含值吗?

标签 c

我有这个关于虚拟内存的问题,因为我想更好地了解应用于分页的写时复制机制。

  1. 假设我们在代码中有 int a = 5,那么根据我的理解,这会在此过程中将 a 与某个虚拟地址相关联,并且然后这个虚拟地址将根据页表转换为物理地址。所以我的问题是:虚拟地址只是地址,它不包含诸如5之类的值。另外,我上面的理解可能是错误的。

  2. 基于这种理解,如果我fork一个新进程,该子进程最初将具有相同的虚拟地址和物理地址。子进程的页表将被标记为只读。只有当子进程尝试进行写入时,操作系统才会分配一个新的物理页并进行复制。我的问题:所以你只需更改页表中的一项即可。其他部分仍然是某种只读内存,因此您没有副本,但指向与父进程相同的物理地址

  3. 我在 Wiki 上发现了以下内容:通过将某些内存页标记为只读并记录页数,可以使用页表有效地实现写时复制对页面的引用。当数据写入这些页面时,内核会拦截写入尝试并分配一个新的物理页面,并使用写时复制数据进行初始化,尽管如果只有一个引用,则可以跳过分配 。然后,内核用新的(可写)页更新页表,减少引用数,并执行写入。新的分配确保一个进程的内存更改在另一个进程中不可见。 我不明白:(1)。为什么我需要统计页面的引用次数?我无法不去思考这样做的好处。 看起来,好吧,我们知道不需要复制的进程总数,但是我们需要知道这些进程到底是什么吗? (2)。如果只有一个引用,为什么可以跳过分配?我假设创建父进程时 ref_cnt 全局数据(实际上每个进程)将为 0,那么当创建子进程时,父进程中的 ref_cnt 现在将为 1。那么当父进程创建另一个子进程时,父进程中的ref_cnt现在将为2,但我们仍然可以跳过分配步骤(因为三个页表是相同的,我们不需要分配新的物理页)?

最佳答案

您对第 1 部分和第 2 部分的理解是正确的(有一些简化)。对于第 3 部分中的问题:

  1. 为什么我需要统计页面的引用次数?

你在上面写了它:这样当引用计数为1时你就知道你不需要复制它,因为没有其他人在看它。

  • 如果只有一个引用,为什么可以跳过分配?我假设 ref_cnt 在父进程中为 0,在子进程中为 1。
  • 引用计数必须是全局的,而不是每个进程的。

    关于c - 我有一个关于虚拟内存的问题,它实际上包含值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57336284/

    相关文章:

    c - 预期为 ‘struct matrix_t *’,但参数的类型为 ‘struct matrix_t *’ ?_?没有不同

    c - Malloc 和 Realloc 结构数组

    c - tolower() 和 toupper() 不起作用

    c - 如何在 Windows 7 上使用 Vim 的 'make' 命令和 Visual Studio 的编译器编译 C 程序?

    C代码: how to detect duplicate function declarations

    c++ - 哪个文件在 Windows Embedded Compact 7.0 上配置缓存?

    c - 是否有一个程序可以作为并行程序正确执行但不能作为顺序程序正确执行?

    c - 有效地处理 c 中的文件

    c - 输出数组为 "String",在 c 中用逗号分隔

    c - 循环中的 opencl 运行时错误 (Clenqueuewritebuffer)