首页 | Linux 基础 | 资讯动态 | Linux 应用 | Linux 服务器 | Linux 开发 | Linux 安全 | 专题 | 联盟论坛
  当前位置:主页>Linux 开发>linux 内核>文章内容
如何利用异常表处理Linux内核态缺页问题
来源:http://www.unix5.com 作者:linux爱好者 发布时间:2008-04-28  
 

前言

在程序的执行过程中,因为遇到某种障碍而使 CPU 无法最终访问到相应的物理内存单元,即无法完成从虚拟地址到物理地址映射的时候,CPU 会产生一次缺页异常,从而进行相应的缺页异常处理。基于 CPU 的这一特性,Linux 采用了请求调页(Demand Paging)和写时复制(Copy On Write)的技术

1. 请求调页是一种动态内存分配技术,它把页框的分配推迟到不能再推迟为止。这种技术的动机是:进程开始运行的时候并不访问地址空间中的全部内容。事实上,有一部分地址也许永远也不会被进程所使用。程序的局部性原理也保证了在程序执行的每个阶段,真正使用的进程页只有一小部分,对于临时用不到的页,其所在的页框可以由其它进程使用。因此,请求分页技术增加了系统中的空闲页框的平均数,使内存得到了很好的利用。从另外一个角度来看,在不改变内存大小的情况下,请求分页能够提高系统的吞吐量。当进程要访问的页不在内存中的时候,就通过缺页异常处理将所需页调入内存中。

2. 写时复制主要应用于系统调用fork,父子进程以只读方式共享页框,当其中之一要修改页框时,内核才通过缺页异常处理程序分配一个新的页框,并将页框标记为可写。这种处理方式能够较大的提高系统的性能,这和Linux创建进程的操作过程有一定的关系。在一般情况下,子进程被创建以后会马上通过系统调用execve将一个可执行程序的映象装载进内存中,此时会重新分配子进程的页框。那么,如果fork的时候就对页框进行复制的话,显然是很不合适的。

在上述的两种情况下出现缺页异常,进程运行于用户态,异常处理程序可以让进程从出现异常的指令处恢复执行,使用户感觉不到异常的发生。当然,也会有异常无法正常恢复的情况,这时,异常处理程序会进行一些善后的工作,并结束该进程。也就是说,运行在用户态的进程如果出现缺页异常,不会对操作系统核心的稳定性造成影响。那么对于运行在核心态的进程如果发生了无法正常恢复的缺页异常,应该如何处理呢?是否会导致系统的崩溃呢?是否能够解决好内核态缺页异常对于操作系统核心的稳定性来说会产生很大的影响,如果一个误操作就会造成系统的Oops,这对于用户来说显然是不能容忍的。本文正是针对这个问题,介绍了一种Linux内核中所采取的解决方法。

在读者继续往下阅读之前,有一点需要先说明一下,本文示例中所选的代码取自于Linux-2.4.0,编译环境是gcc-2.96,objdump的版本是2.11.93.0.2,具体的版本信息可以通过以下的命令进行查询:

 

$ gcc -v
  Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
  gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)
  $ objdump -v
  GNU objdump 2.11.93.0.2 20020207
  Copyright 2002 Free Software Foundation, Inc.
  

GCC的扩展功能

由于本文中会用到GCC的扩展功能,即汇编器as中提供的.section伪操作,在文章开始之前我再作一个简要的介绍。此伪操作对于不同的可执行文件格式有不同的解释,我也不一一列举,仅对我们所感兴趣的Linux中常用的ELF格式的用法加以描述,其指令格式如下:

 

 .section NAME[, "FLAGS"]
  

大家所熟知的C程序一般由以下的几个部分组成:代码段(text section)、初始化数据段(data section)、非初始化数据段(bss section)、栈(heap)以及堆(stack),具体的地址空间布局可以参考《UNIX环境高级编程》一书。

在Linux内核中,通过使用.section的伪操作,可以把随后的代码汇编到一个由NAME指定的段中。而FLAGS字段则说明了该段的属性,它可以用下面介绍的单个字符来表示,也可以是多个字符的组合。

'a' 可重定位的段;

'w' 可写段;

'x' 可执行段;

'W' 可合并的段;

's' 共享段。

举个例子来说明,读者在后面会看到的:.section .fixup, "ax"。这样的一条指令定义了一个名为.fixup的段,随后的指令会被加入到这个段中,该段的属性是可重定位并可执行。 ezZLinux联盟

内核缺页异常处理

运行在核心态的进程经常需要访问用户地址空间的内容,但是谁都无法保证内核所得到的这些从用户空间传入的地址信息是"合法"的。为了保护内核不受错误信息的攻击,需要验证这些从用户空间传入的地址信息的正确性。

在老版本的Linux中,这个工作是通过函数verify_area来完成的:

 


共6页: 上一页 1 [2] [3] [4] [5] [6] 下一页
 
如果您对本文有任何疑问或者建议,请到论坛讨论区发表您的意见: >> 论坛入口
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
  热点文章
·使用 Linux 系统调用的内核命令
·Linux 2.6.11内核文件IO系统调用
·Linux操作系统的源代码目录树结
·Linux用户态与内核态的交互讲解
·Linux内核对I/O端口的管理实现(
·深入分析 Linux操作系统的内核链
·Linux内核可装载模块对设备驱动
·概述Linux系统的驱动框架及驱动
·详解Linux 2.6内核新文件系统变
·Linux系统可卸载内核模块完全指
·FreeBSD手册讲解(一)--配置FreeB
·编译Linux操作系统的内核讲解
  相关文章
·Linux操作系统核心的汉字显示机
·Linux下的中文显示和支持常见问
·Linux操作系统“警惕”内核汉化
·Linux内核源代码学习概述
·简析Linux与FreeBSD的syscall
·如何在Linux内核中的实现SYN Coo
·Linux系统内核漏洞分析
·深入学习LINUX内核之七(图文讲解
·深入学习LINUX内核之六(图文讲解
·深入学习LINUX内核之五(图文讲解
·深入学习LINUX内核之四(图文讲解
·深入学习LINUX内核之三(图文讲解

本站信息源至:互联网络,均为学习,交流所用,如有版权问题,请联系我们.
站长QQ:397422079 E_mail:riechelr_hl@unix5.com
转载本站内容请注明原作者名.谢谢!