资料分类
硬件内存 |主板 |CPU |硬盘 |显卡 |网卡 |声卡 |光驱 | 笔记本专区 | 刻录机| 鼠标| 键盘 |病毒专题

办公:打印机|扫描仪|复印机 网络ADSL|局域网| 防火墙 | 路由器 | 无线网络 | 系统winxp win2003 winvisa 服务器

常用维修软件: GHOST | DM | PC3000 | NDD | PQMagic | 效率源 | 还原精灵 电子基础: 电子元件 | 工具应用 | 电路基础
您现在的位置: 龙腾电脑维修网 >> 技术资料 >> 软件专栏 >> linux >> 文章正文

利用异常表处理Linux内核态缺页异常

利用异常表处理Linux内核态缺页异常


该函数首先从CPU的控制寄存器CR2中获取出现缺页异常的虚拟地址。由于缺页异常处理程序需要处理的缺页异常类型很多,分支也很复杂。基于本文的主旨,我们只关心以下的几种内核缺页异常处理的情况:

  1." 程序要访问的内核地址空间的内容不在内存中,先跳转到标号vmalloc_fault,如果当前访问的内容所对应的页目录项不在内存中,再跳转到标号no_context;

  2. 缺页异常发生在中断或者内核线程中,跳转到标号no_context;

  3. 程序在核心态运行时访问用户空间的数据,被访问的数据不在内存中

  a) 出现异常的虚拟地址在进程的某个vma中,但是系统内存无法分配空闲页框(page frame),则先跳转到标号out_of_memory,再跳转到标号no_context;

  b) 出现异常的虚拟地址不属于进程任一个vma,而且不属于堆栈扩展的范畴,则先跳转到标号bad_area,最终也是到达标号no_context。

  从上面的这几种情况来看,我们关注的焦点最后集中到标号no_context处,即对函数search_exception_table的调用。这个函数的作用就是通过发生缺页异常的指令(regs->eip)在异常表(exception table)中寻找下一条可以继续运行的指令(fixup)。这里提到的异常表包含一些地址对,地址对中的前一个地址表示出现异常的指令的地址,后一个表示当前一个指令出现错误时,程序可以继续得以执行的修复地址。

  如果这个查找操作成功的话,缺页异常处理程序将堆栈中的返回地址(regs->eip)修改成修复地址并返回,随后,发生异常的进程将按照fixup中安排好的指令继续执行下去。当然,如果无法找到与之匹配的修复地址,系统只有打印出出错信息并停止运作。

  那么,这个所谓的修复地址又是如何生成的呢?是系统自动生成的吗?答案当然是否定的,这些修复指令都是编程人员通过as提供的扩展功能写进内核源码中的。下面我们就来分析一下其实现机制。

  异常表的实现机制

  笔者取include/asm-i386/uaccess.h中的宏定义__copy_user编写了一段程序作为例子加以讲解。

  

/* hello.c */ 
  #include  
  #include  
   
  #define __copy_user(to,from,size) do 
 { int __d0, __d1; __asm__ __volatile__ 
( "0: rep; movsl\n" " movl %3,%0\n" "1: rep; movsb\n" 
 "2:\n" ".section .fixup,\"ax\"\n"  
"3: lea 0(%3,%0,4),%0\n" " jmp 2b\n"  
".previous\n" ".section __ex_table,\"a\"\n" 
 " .align 4\n" 
 " .long 0b,3b\n" " .long 1b,2b\n" 
 ".previous" : "=&c"(size), "=&D" (__d0),  
"=&S" (__d1) : "r"(size & 3), "0"(size / 4), "1"(to), 
 "2"(from) : "memory"); } while (0) 
   
  int main(void) 
  { 
   const char *string = "Hello, world!"; 
   char buf[20]; 
   unsigned long n, m; 
   
   m = n = strlen(string); 
   __copy_user(buf, string, n); 
   buf[m] = '\0'; 
   printf("%s\n", buf); 
   exit(0); 
  }

  先看看本程序的执行结果:

  

$ gcc hello.c -o hello 
   $ ./hello 
  Hello, world!

   

  显然,这就是一个简单的"hello world"程序,那为什么要写得这么复杂呢?程序中的一大段汇编代码在内核中才能体现出其价值,笔者将其加入到上面的程序中,是为了后面的分析而准备的。

上一页  [1] [2] [3] [4] [5] [6] 下一页

  • 上一篇文章:

  • 下一篇文章:

  • 如果您发现该文章有错误,请通知管理员,谢谢!
    作者:未知
    点击数:
    更新时间:2006-10-23 16:38:52
    我要发表评论
    本站论坛
    返回文章首页
    我要发表文章
    评论内容只代表网友观点,与本站立场无关!

    公司简介 - 联系方法 - 合作伙伴 - RSS订阅 - 意见反馈 - Dragon computer(龙腾电脑英文站) - 版权声明
    @ 2006-2008龙腾电脑 版权所有. ALL RIGHTS RESERVED. 浙ICP备05046531号
    友情连接QQ:42738612 本站QQ群:28651784 26926005