【问题标题】:Why there is no SIGSEGV signal on copy on write?为什么在写入时复制时没有 SIGSEGV 信号?
【发布时间】:2012-04-21 03:34:57
【问题描述】:

copy-on-write article on wikipedia 说写时复制通常是通过对页面提供只读访问来实现的,因此当一个页面被写入时,页面错误陷阱处理程序可以为其映射一个唯一的物理内存页面。所以我的问题是为什么当这种页面错误发生时用户级应用程序没有收到 SIGSEGV 信号?毕竟,wikipedia article on SIGSEGV 表示 SIGSEGV 是当进程进行无效内存引用或分段错误时发送给进程的信号。所以在这种情况下,即写时复制的情况下,为什么没有向进程发送 SIGSEGV。

【问题讨论】:

    标签: memory-management operating-system copy-on-write page-fault


    【解决方案1】:

    我知道这个问题已经有一段时间了,但我想稍微扩展一下 Alexey 的回答。

    写时复制(我假设您说的是虚拟内存而不是文件系统)通常是这样工作的:

    1. 操作系统知道在写入时需要复制哪些页面。 (它们是进程专用的页面。)这些页面在硬件中标记为只读。但是,进程的虚拟内存映射将页面标记为可读和可写。这意味着用户进程认为它拥有对相关页面的完全访问权限。
    2. 当用户进程尝试写入其中一个页面时,会生成一个页面错误,因为处理器识别出该页面是只读的(基于之前的硬件标记)。页面错误有点像段错误,但对于内核而不是用户进程。
    3. 这会触发页面错误处理程序在内核中运行,它会查看有问题的页面并发现它是尚未复制的私有页面。处理程序将创建页面的副本并将副本标记为可写。
    4. 然后处理程序会将旧页面的地址替换为虚拟到物理转换表中的新地址并退出。
    5. 此时用户进程将重试最后一条指令,这一次写入将成功,因为新页面在虚拟内存映射(用户进程的内存权限视图)和硬件(内核的内存权限视图)级别。

    每次发生分段错误时都会生成一个页面错误,但大多数页面错误由内核处理,并且永远不会作为段错误传递给导致它们的进程。在较低级别处理页面错误的原因有很多,包括:

    • 被访问的页面由于长时间未使用而被调出到磁盘。操作系统必须将其带回内存,以便进程可以再次使用它。
    • 进程第一次访问新分配的页,实际物理页尚未分配。操作系统必须先分配一个页面,然后将其插入到虚拟到物理的转换表中,然后才能实际使用内存。
    • 操作系统正在播放硬件页面访问权限技巧,以允许它监视对特定页面的访问。这就是写时复制中发生的情况,但它也可以有其他用途。考虑一种操作系统级别的虚拟化技术,例如kvm,其中写入来宾操作系统内存中的内存映射设备的位置实际上应该写入主机操作系统中的文件或显示。

    【讨论】:

      【解决方案2】:

      COW 的主要思想是,COW 对用户进程完全透明,就好像它完全拥有内存,没有任何共享。

      【讨论】:

      • 但是当一个进程在 fork 上复制自己时会发生什么?我的意思是在分叉之后,如果原始进程修改了某个页面,则会为其分配一个新的物理页面,但是如果分叉的进程之后修改了相同的页面,则它不会分配新的页面,因为原始进程现在已经有了不同的页面。这是如何实现的?
      • 操作系统负责所有这些页面错误处理、内存分配和映射以及数据复制。
      • user1018562,在 fork parent 的内存被 COWed 之后 - 标记为只读,因为现在有其他进程链接到同一内存。如果他们中的任何人写入,它将获得页面错误并且页面将被拆分(deCOWed)。内核将分配新页面,复制旧数据,然后重新启动失败的写入。除了增加的次要页面错误计数器(检查 /usr/bin/time)外,它对用户是透明的。 PS:fork+exec 是个特例。
      猜你喜欢
      • 1970-01-01
      • 2014-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多