为什么写入时拷贝上没有SIGSEGV信号?

为什么写入时拷贝上没有SIGSEGV信号?

问题描述:

copy-on-write article on wikipedia表示写入时复制通常通过给页面提供只读访问权限来实现,以便在写入页面时,页面错误陷阱处理程序可以为其设置唯一的物理内存页面。所以我的问题是为什么当这样的页面错误发生时,用户级应用程序没有收到SIGSEGV信号?最后,wikipedia article on SIGSEGV表示SIGSEGV是发送给进程的信号,当它导致无效的内存引用或分段错误时。所以在这种情况下,即在写入时复制的情况下,为什么没有SIGSEGV发送到进程。为什么写入时拷贝上没有SIGSEGV信号?

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

+0

但是当一个进程在fork上自我复制时会发生什么?我的意思是在fork之后,如果原始进程修改某个页面,则会为其分配一个新的物理页面,但如果分叉进程之后修改了同一页面,则不会分配一些新页面,因为原始进程现在已经有不同的页面。这是如何实现的? – pythonic 2012-04-21 03:49:42

+0

操作系统负责所有这些页面错误处理,内存分配和映射以及数据复制。 – 2012-04-21 03:51:23

+0

user1018562,后叉父母的内存COWed - 标记为只读,因为现在有其他进程链接到相同的内存。如果他们中的任何人写入,它将得到页面错误并且页面将被分割(deCOWed)。内核将分配新页面,复制旧数据,然后重新启动失败的写入。除了增加的次要页面错误计数器(使用/ usr/bin/time检查)外,它对用户是透明的。 PS:fork + exec是一个特例。 – osgx 2012-12-19 08:45:42

我知道这已经过了一段时间,因为这是被问到的,但我想扩展Alexey的答案。

写入时复制(我假设你在谈论的虚拟内存,而不是文件系统)通常工作像这样:

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

每次发生分段错误时都会生成页面错误,但大多数页面错误都是由内核处理的,并且不会传递给造成段错误的进程。有很多原因可能会导致较低级别的页面错误,包括:

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