段错误(根源)

        任何现代计算机系统都必须为操作系统提供手段来控制对存储器系统的访问。不应该允许一个用户进程修改它的只读文本段,而且也部允许它读或修改任何内核代码中的代码和数据结构。不应该循序它读或者写其他进程的私有存储器,而且允许它修改任何与其他进程共享的虚拟页面,除非所有的共享者都显示的允许它这么做(通过调用明确的进程间通信系统调用)。

        就像我们所看到的,提供独立的地址空间使得分离不同进程的私有存储器变得容易。但是,地址翻译机制可以以一种自然的方式扩展到提供更好的访问控制。因为每次CPU生成一个地址时,地址翻译硬件都会读一个PTE,所以通过在PTE上添加一些额外的许可位来控制对一个虚拟页面内容的访问,十分简单。如下图展示了一般的概念。

段错误(根源)

       在这个示例中,我们已经添加了三个许可位到每个PTE。SUP位表示进程是否必须运行在内核(超级用户)模式下才能访问该页。运行在内核模式中的进程可以访问任何页面,但是运行在用户模式下的进程只允许访问那些SUP位0的页面,READ位和WRITE位控制对页面的读和写访问。例如,如果进程i运行在用户模式下,那么它有读VP0和读写VP1的权限。然而,不允许它访问VP2.

     如果一条指令违反了这些许可条件,那么CPU就触发一个一般保护故障,将控制传递给一个内核中的异常处理程序,Unix shell典型地将这种异常报告为“段错误(segmentation fault)”。我认为这是我们在写程序中遇到段错误的最根本的原因。