首页 | Linux 基础 | 资讯动态 | Linux 应用 | Linux 服务器 | Linux 开发 | Linux 安全 | 专题 | 联盟论坛
  当前位置:主页>Linux 开发>linux 内核>文章内容
借助异常表处理Linux内核态缺页异常情况
来源:http://www.unix5.com 作者:riechelr_hl 发布时间:2007-07-12  
/* 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"程序,那为什么要写得这么复杂呢?程序中的一大段汇编代码在内核中才能体现出其价值,笔者把其加入到上面的程序中,是为了后面的分析而准备的。

系统在核心态运行的时候,参数是通过寄存器来传递的,由于寄存器所能够传递的信息有限,所以传递的参数大多数是指针。要使用指针所指向的更大块的数据,就需要把用户空间的数据拷贝到系统空间来。上面的__copy_user在内核中正是扮演着这样的一个拷贝数据的角色,当然,内核中这样的宏定义还很多,笔者也只是取其中的一个来讲解,读者如果感兴趣的话可以看完本文以后自行学习。

如果读者对于简单的嵌入式汇编还不是很了解的话,可以参考《Linux内核源代码情景分析》一书。

 

下面我们把程序编译成汇编程序来加以分析:

 

$ gcc -S hello.c
  /* hello.s */
   movl -60(%ebp), %eax
   andl $3, %eax
   movl -60(%ebp), %edx
   movl %edx, %ecx
   shrl $2, %ecx
   leal -56(%ebp), %edi
   movl -12(%ebp), %esi
  #APP
   0: rep; movsl
   movl %eax,%ecx
  1: rep; movsb
  2:
  .section .fixup,"ax"
  3: lea 0(%eax,%ecx,4),%ecx
   jmp 2b
  .previous
  .section __ex_table,"a"
   .align 4
   .long 0b,3b
   .long 1b,2b
  .previous
  #NO_APP
   movl %ecx, %eax
 

从上面通过gcc生成的汇编程序中,我们可以很容易的找到访问用户地址空间的指令,也就是程序中的标号为0和1的两条语句。而程序中伪操作.section的作用就是定义了.fixup和__ex_table这样的两个段,那么这两段在可执行程序中又是怎么样安排的呢?下面就通过objdump给读者一个直观的概念:

 

 $ objdump --section-headers hello
  hello:   file format elf32-i386
  
  Sections:
  Idx Name     Size   VMA    LMA    File off Algn
   0 .interp    00000013 080480f4 080480f4 000000f4 2**0
           CONTENTS, ALLOC, LOAD, READONLY, DATA
   ………………………………
   9 .init     00000018 080482e0 080482e0 000002e0 2**2
           CONTENTS, ALLOC, LOAD, READONLY, CODE
   10 .plt     00000070 080482f8 080482f8 000002f8 2**2
           CONTENTS, ALLOC, LOAD, READONLY, CODE
   11 .text     000001c0 08048370 08048370 00000370 2**4
           CONTENTS, ALLOC, LOAD, READONLY, CODE
   12 .fixup    00000009 08048530 08048530 00000530 2**0
           CONTENTS, ALLOC, LOAD, READONLY, CODE
   13 .fini     0000001e 0804853c 0804853c 0000053c 2**2
           CONTENTS, ALLOC, LOAD, READONLY, CODE
   14 .rodata    00000019 0804855c 0804855c 0000055c 2**2
           CONTENTS, ALLOC, LOAD, READONLY, DATA
   15 __ex_table  00000010 08048578 08048578 00000578 2**2
           CONTENTS, ALLOC, LOAD, READONLY, DATA
   16 .data     00000010 08049588 08049588 00000588 2**2
           CONTENTS, ALLOC, LOAD, DATA
           CONTENTS, READONLY
   ………………………………
   26 .note     00000078 00000000 00000000 0000290d 2**0
           CONTENTS, READONLY

共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
转载本站内容请注明原作者名.谢谢!