首页 | Linux 基础 | 资讯动态 | Linux 应用 | Linux 服务器 | Linux 开发 | Linux 安全 | 专题 | 联盟论坛
  当前位置:主页>Linux 开发>linux 内核>文章内容
借助异常表处理Linux内核态缺页异常情况
来源:http://www.unix5.com 作者:riechelr_hl 发布时间:2007-07-12  
 

上面通过objdump显示出来的可执行程序的头部信息中,有一些是读者所熟悉的,例如.text、.data以及被笔者省略掉的.bss,而我们所关心的是12和15,也就是.fixup和__ex_table。对照hello.s中段的定义来看,两个段声明中的FLAGS字段分别为'ax'和'a',而objdump的结果显示,.fixup段是可重定位的代码段,__ex_table段是可重定位的数据段,两者是吻合的。

那么为什么要通过.section定义独立的段呢?为了解开这个问题的答案,我们需要进一步看看我们所写的代码在可执行文件中是怎么样表示的。

 

$objdump --disassemble --section=.text hello
  hello:   file format elf32-i386
  
  Disassembly of section .text:
  8048498: 8b 45 c4       mov   0xffffffc4(%ebp),%eax
  804849b: 83 e0 03       and   $0x3,%eax
  804849e: 8b 55 c4       mov   0xffffffc4(%ebp),%edx
  80484a1: 89 d1        mov   %edx,%ecx
  80484a3: c1 e9 02       shr   $0x2,%ecx
  80484a6: 8d 7d c8       lea   0xffffffc8(%ebp),%edi
  80484a9: 8b 75 f4       mov   0xfffffff4(%ebp),%esi
  80484ac: f3 a5        repz movsl %ds:(%esi),%es:(%edi)
  80484ae: 89 c1        mov   %eax,%ecx
  80484b0: f3 a4        repz movsb %ds:(%esi),%es:(%edi)
  80484b2: 89 c8        mov   %ecx,%eax
  

前面的hello.s中的汇编片断在可执行文件中就是通过上面的11条指定来表达,读者也许会问,由.section伪操作定义的段怎么不见了?别着急,慢慢往下看,由.section伪操作定义的段并不在正常的程序执行路径上,它们是被安排在可执行文件的其它地方了:

 

 $objdump --disassemble --section=.fixup hello
  hello:   file format elf32-i386
  
  Disassembly of section .fixup:
  
  08048530 <.fixup>:
  8048530: 8d 4c 88 00      lea  0x0(%eax,%ecx,4),%ecx
  8048534: e9 79 ff ff ff    jmp  80484b2 <main+0x42>
  

由此可见,.fixup是作为一个单独的段出现在可执行程序中的,而此段中所包含的语句则正好是和源程序hello.c中的两条语句相对应的。

把.fixup段和.text段独立开来的目的是为了提高CPU流水线的利用率。熟悉体系结构的读者应该知道,当前的CPU引入了流水线技术来加快指令的执行,即在执行当前指令的同时,要把下面的一条甚至多条指令预取到流水线中。这种技术在面对程序执行分支的时候遇到了问题:如果预取的指令并不是程序下一步要执行的分支,那么流水线中的所有指令都要被排空,这对系统的性能会产生一定的影响。在我们的这个程序中,如果把.fixup段的指令安排在正常执行的.text段中,当程序执行到前面的指令时,这几条很少执行的指令会被预取到流水线中,正常的执行必然会引起流水线的排空操作,这显然会降低整个系统的性能。

下面我们就可以看到异常表是怎么样形成的了:

 

$objdump --full-contents --section=__ex_table hello
  hello:   file format elf32-i386
  
  Contents of section __ex_table:
  8048578 ac840408 30850408 b0840408 b2840408 ....0...........

  

由于x86使用小尾端的编址方式,上面的这段数据比较凌乱。让我把上面的__ex_table中的内容转变成大家通常看到的样子,相信会更容易理解一些:

 

8048578 80484ac 8048530 80484b0 80484b2 ....0...........

  

上面的红色部分就是我们最感兴趣的地方,而这段数据是怎么样形成的呢?把前面objdump生成的可执行程序中的汇编语句和hello.c中的源程序结合起来看,就可以发现一些有趣的东西了!

先让我们回头看看hello.c中__ex_table段的语句 .long 0b,3b。其中标签0b(b代表backward,即往回的标签0)是可能出现异常的指令的地址。结合objdump生成的可执行程序.text段的汇编语句可以知道标签0就是80484ac:

共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系统内核研究之可执行文件
·Linux系统内核网络参数意义以及
·SYN Cookie原理以及在Linux系统
·Linux操作系统动态函式库讲解(
·Linux操作系统动态函式库讲解(二
·Linux系统内核:修改TCP/IP调优参
·Linux内核空间保护与空间数据传
·编译支持NTFS的Linux系统内核模

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