分类:
2015-03-09 15:43:34
我们引用wiki上的一段话来回答这个问题。
A segmentation fault (often shortened to SIGSEGV) is a particular error condition that can occur during the operation of . A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).
is one approach to and protection in the . It has been superseded by for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.
On operating systems, a process that accesses an invalid memory address receives the . On , a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION .
上述文字没有给出SIGSEGV的定义,仅仅说它是“计算机软件操作过程中的一种错误情况”。文字描述了SIGSEGV在何时发生,即“当程序试图访问不被允许访问的内存区域(比如,尝试写一块属于操作系统的内存),或以错误的类型访问内存区域(比如,尝试写一块只读内存)。这个描述是准确的。为了加深理解,我们再更加详细的概括一下SIGSEGV。
Ø SIGSEGV是在访问内存时发生的错误,它属于内存管理的范畴
Ø SIGSEGV是一个用户态的概念,是操作系统在用户态程序错误访问内存时所做出的处理。
Ø 当用户态程序访问(访问表示读、写或执行)不允许访问的内存时,产生SIGSEGV。
Ø 当用户态程序以错误的方式访问允许访问的内存时,产生SIGSEGV。
从用户态程序开发的角度,我们并不需要理解操作系统复杂的内存管理机制,这是和硬件平台相关的。但是,了解内核发送SIGSEGV信号的流程,对我们理解SIGSEGV是很有帮助的。在《Understanding Linux Kernel Edition 3》和《Understanding the Linux Virtual Memory Manager》相关章节都有一幅总图对此描述,对比之下,笔者认为ULK的图更为直观。
图1. SIGSEGV Overview
图1红色部分展示了内核发送SIGSEGV信号给用户态程序的总体流程。当用户态程序访问一个会引发SIGSEGV的地址时,硬件首先产生一个page fault,即“缺页异常”。在内核的page fault处理函数中,首先判断该地址是否属于用户态程序的地址空间[*]。以Intel的32bit IA32架构的CPU为例,用户态程序的地址空间为[0,3G],内核地址空间为[3G,4G]。如果该地址属于用户态地址空间,检查访问的类型是否和该内存区域的类型是否匹配,不匹配,则发送SIGSEGV信号;如果该地址不属于用户态地址空间,检查访问该地址的操作是否发生在用户态,如果是,发送SIGSEGV信号。
[*]这里的用户态程序地址空间,特指程序可以访问的地址空间范围。如果广义的说,一个进程的地址空间应该包括内核空间部分,只是它不能访问而已。
图2更为详细的描绘了内核发送SIGSEGV信号的流程。在这里我们不再累述图中流程,在后面章节的例子中,笔者会结合实际,描述具体的流程。
图2 SIGSEGV detailed flow