Linux内核源代码解释让你真正了解linux.ppt
解读Linux内核源代码让您真正明白Linux操作系统 序 一些基本概念 操作系统的基本概念 I386系统的基本概念 Linux简介 源码阅读和project环境 Linux 2.6.26 源码简介 操作系统的基本概念 任何计算机系统都包含一个基本的程序集合,称为操作系统。 内核(进程管理,进程调度,进程间通讯机制,内存管理,中断异常处理,文件系统,I/O系统,网络部分) 其他程序(例如函数库,shell程序等等) 操作系统的目的 与硬件交互,管理所有的硬件资源 为用户程序(应用程序)提供一个良好的执行环境 I386系统的基本概念 代码的运行 堆栈的概念 内核态与用户态 中断/异常/系统调用 虚拟内存 代码的运行 关键寄存器 cs : eip:总是指向下一条的指令地址 顺序执行:总是指向地址连续的下一条指令 跳转/分支:执行这样的指令的时候,cs : eip的值会根据程序需要被修改 call:将当前cs : eip的值压入栈顶,cs : eip指向被调用函数的入口地址 ret:从栈顶弹出原来保存在这里的cs : eip的值,放入cs : eip中 发生中断时??? ???? I386系统的基本概念 代码的运行 堆栈的概念 内核态与用户态 中断/异常/系统调用 虚拟内存 堆栈的概念 堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间 函数调用框架 传递参数 保存返回地址 提供局部变量空间 等等 C语言编译器对堆栈的使用有一套的规则 了解堆栈存在的目的和编译器对堆栈使用的规则是理解操作系统一些关键性代码的基础 以x86体系结构为例 堆栈寄存器和堆栈操作 堆栈相关的寄存器 esp,堆栈指针(stack pointer) ebp,基址指针(base pointer) 堆栈操作 push栈顶地址减少4个字节(32位) pop栈顶地址增加4个字节 ebp在C语言中用作记录当前函数调用基址 利用堆栈实现函数调用和返回 函数堆栈框架的形成 call xxx 执行call之前 执行call时,cs : eip原来的值指向call下一条指令,该值被保存到栈顶,然后cs : eip的值指向xxx的入口地址 进入xxx 第一条指令: pushl %ebp 第二条指令: movl %esp, %ebp 函数体中的常规操作,可能会压栈、出栈 退出xxx movl %ebp,%esp popl %ebp ret C语言中还使用堆栈进行 参数的传递 局部变量的使用 一段小程序 源文件:test.c 这是一个很简单的C程序 main函数中调用了函数p1和p2 首先使用gcc生成test.c的可执行文件test 然后使用objdump –S获得test的反汇编文件 观察程序运行时堆栈的变化 另一段小程序和前一段小程序稍有不同 观察程序运行时堆栈的变化 I386系统的基本概念 代码的运行 堆栈的概念 内核态与用户态 中断/异常/系统调用 虚拟内存 用户态和内核态的概念 Why? 假定不区分 用户直接修改操作系统的数据 用户直接调用操作系统的内部函数 用户直接操作外设 用户任意读/写物理内存 因此,要区分用户态和内核态: 禁止用户程序和底层硬件直接打交道 (最简单的例子,如果用户程序往硬件控制寄存器写入不恰当的值,可能导致硬件无法正常工作) 禁止用户程序访问任意的物理内存 (否则可能会破坏其他程序的正常执行,如果对核心内核所在的地址空间写入数据的话,会导致系统崩溃) 什么是用户态和内核态? 一般现代CPU都有几种不同的指令执行级别 在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态 而在相应的低级别执行状态下,代码的掌控范围会受到限制。只能在对应级别允许的范围内活动 举例:intel x86 CPU有四种不同的执行级别0-3,Linux只使用了其中的0级和3级分别来表示内核态和用户态 如何区分一段代码是核心态还是用户态 cs寄存器的最低两位表明了当前代码的特权级 CPU每条指令的读取都是通过cs:eip这两个寄存器:其中cs是代码段选择寄存器,eip是偏移量寄存器。 上述判断由硬件完成 一般来说在Linux中,地址空间是一个显著的标志:0xc0000000以上的地址空间只能在内核态下访问,00xbfffffff的地址空间在两种状态下都可以访问 注意:这里所说的地址空间是逻辑地址而不是物理地址 I386系统的基本概念 代码的运行 堆栈的概念 内核态与用户态 中断/异常/系统调用 虚拟内存 中断和异常 中断(广义)会改变处理器执行指令的顺序,通常与CPU芯片内部或外部硬件电路产生的电信号相对应 中断——异步的:由硬件随机产生,在程序执行的任何时候可能出现 异常——同