版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux内核分析
TheAnalysisoftheLinuxKernelLinux操作系统分析Linux内核分析
TheAnalysisofthe教材Linux内核源代码情景分析毛德操
胡希明著浙江大学出版社2001年9月第1版
Linux操作系统分析教材Linux内核源代码情景分析Linux操作系统分析参考书目LinuxKernel中文版,DavidARusling著Linux内核完全注释,赵炯著,,2003年1.2.2修正版Linux内核2.4版源代码分析大全,李善平等著,机械工业出版社,2002年1月第1版UNIX操作系统设计,MJBach著,机械工业出版社,2001年现代操作系统[英文],AndrewS.Tanenbaum著,机械工业出版社,2002年动手写自己的操作系统,于渊编著,电子工业出版社,2005年8月Linux操作系统分析参考书目LinuxKernel中文版,DavidAR本课程需要的基础知识具备操作系统的基础知识具备C语言程序设计的基础知识粗通汇编语言编程熟悉UNIX用户界面,略知微机系统结构,尤其是保护模式,分段、分页机制。Linux操作系统分析本课程需要的基础知识具备操作系统的基础知识Linux操作系统第一章预备知识本章主要内容Linux内核的基础知识为什么分析操作系统?为个么选择Linux?Linux和Linux内核的关系Linux的技术特点Linux内核的组成结构及版本Linux源代码的分析方法、工具其他相关基础知识Linux内核源代码中的C语言代码的特点Linux内核源代码中的汇编语言代码的特点x86的虚拟存储技术Linux操作系统分析第一章预备知识本章主要内容Linux操作系统分析为什么分析操作系统?分析操作系统的目的深入理解一个操作系统的内在机制及其实现机理学习系统软件的设计方法和实现技巧研究和分析制约操作系统性能的原因不同于学习操作系统的使用普通用户学习通过操作界面使用操作系统程序设计者学习通过系统调用使用操作系统操作系统的设计目的就是为上述两类用户提供统一的使用方式Linux操作系统分析为什么分析操作系统?分析操作系统的目的Linux操作系统分析为什么选择分析Linux?从其发展历史看,它属于现在得到广泛应用的UNIX家族,并已被大量用户认可和接受集中了全世界众多操作系统黑客的技术精华在嵌入式和实时操作系统方面有大量的社会需求源代码开放,容易获取并学习未来24个月嵌入式操作系统的应用调查(2000.9)
Linux操作系统分析为什么选择分析Linux?从其发展历史看,它属于现在得到广泛Linux内核的组成存储管理进程管理设备管理文件系统进程间通信网络Linux操作系统分析Linux内核的组成存储管理Linux操作系统分析Linux的内核结构图Linux操作系统分析Linux的内核结构图Linux操作系统分析Linux内核源代码目录结构(1)arch这个子目录包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是x86。include这个目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。init此目录包含核心启动代码。mm此目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下,如对应于X86的就是arch/x86/mm/fault.c。drivers系统中所有的设备驱动都位于此目录中。它又进一步划分成几类设备驱动,每一种也有对应的子目录,如声卡的驱动对应于drivers/sound。ipc此目录包含了核心的进程间通讯代码。Linux操作系统分析Linux内核源代码目录结构(1)arch这个子目录包含了Linux内核源代码目录结构(2)modules此目录包含已建好可动态加载的模块。fsLinux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext2文件系统对应的就是ext2子目录。kernel主要核心代码。同时与处理器结构相关代码都放在arch/*/kernel目录下。net核心的网络部分代码。里面的每个子目录对应于网络的一个方面。lib此目录包含了核心的库代码。与处理器结构相关库代码被放在arch/*/lib/目录下。scripts此目录包含用于配置核心的脚本文件。Documentation此目录是一些文档,起参考作用。Linux操作系统分析Linux内核源代码目录结构(2)modules此目录包含Linux内核源代码的获取方式商业发行版本附带的发行版内核,通常不是最新的官方网站:中国自由软件库(最新版)发行商网站大学网站/Linux/kernelN/OS/Linux/kernelLinux操作系统分析Linux内核源代码的获取方式商业发行版本附带的发行版内核,Linux源代码的阅读方法和工具(1)Linux源代码的阅读方法阅读顺序纵向,就是顺着程序的执行顺序逐步进行横向,就是分模块进行划分不绝对的,而是经常结合在一起进行Linux的启动的代码就可以顺着linux的启动顺序一步一步地读,大致流程如下(以X86平台为例):./arch/x86/boot/bootSect.S./arch/x86/boot/setup.S./arch/x86/kernel/head.S./init/main.c中的start_kernel()对于内存管理等部分,可以单独拿出来按模块进行阅读分析。Linux操作系统分析Linux源代码的阅读方法和工具(1)Linux源代码的阅读Linux操作系统分析Linux操作系统分析Linux源代码的阅读方法和工具(2)windows环境下利用SourceInsight阅读工具可从/上边下载30天试用版本linux环境下利用lxr(linuxcrossreference)或glimpse等阅读工具进行阅读建议开始最好按顺序阅读启动代码然后进行专题阅读,如进程部分,内存管理部分等。在每个功能函数内部应该一步步来实际上这是一个反复的过程,不可能读一遍就理解Linux操作系统分析Linux源代码的阅读方法和工具(2)windows环境下利SourceInsight软件使用方法选择Project菜单下的new,新建一个工程,输入工程名把欲读的源代码加入(可以整个目录加)后,该软件就分析你所加的源代码。分析完后,就可以进行阅读了。打开相要阅读的文件如果想看某一变量的定义先把光标定位于该变量然后点击工具条上的相应选项或从右键菜单中选择该变量的定义就显示出来对于函数的定义与实现也可以同样操作Linux操作系统分析SourceInsight软件使用方法选择Project菜Linux内核源代码的C语言代码(1)内核的主体是以GNU的C语言编写的,GNU对C语言本身在ANSIC的基础上作了不少扩充使用gcc作为编译工具,gcc同时又是C++编译工具内核具有很多C++语言的特点gcc从C++语言中吸收了inline和const比define更安全,如可定义数据类型等等内核的版本与gcc的版本间有依赖关系Longlongint,用于支持64位的CPU结构为了防止扩展的属性和保留字与变量名的冲突“__保留字__”等价于“保留字”attribute__((属性)),如aligned,packedLinux操作系统分析Linux内核源代码的C语言代码(1)内核的主体是以GNU的Gcc从C++语言中吸收了“inline”和“const”。其实,GNU的C和C++是合为一体的,gcc既是C编译又是C++编译,所以从C++中吸收一些东西到C中是很自然的。从功能上说,inline函数的使用与#define宏定义相似,但更有相对的独立性,也更安全。使用inline函数也有利于程序调试。如果编译时不加优化,则这些inline函数就是普通的,独立的函数,更便于调试。调试好以后,再采用优化重新编译一次,这些inline函数就像宏操作一样融入了引用处的代码中,有利于提高运行效率。由于inline函数的大量使用,相当一部分代码从.c文件移入了.h文件中。Linux操作系统分析Gcc从C++语言中吸收了“inline”和“cLinux内核源代码的C语言代码(2)Do{…}while(0)的作用使{}之间的代码构成一个块执行空操作,如为进程切换作准备举例如果没有Do{…}while(0)Linux操作系统分析Linux内核源代码的C语言代码(2)Do{…}whileLinux内核源代码的C语言代码(3)双链数据结构使得针对这些队列的操作可用于不同数据结构宿主数据结构举例Linux操作系统分析Linux内核源代码的C语言代码(3)双链数据结构LinuxLinux内核源代码的C语言代码(4)宿主结构起始地址的定位举例当前结构中list的地址–当page结构刚好位于地址0时的list地址Linux操作系统分析Linux内核源代码的C语言代码(4)宿主结构起始地址的定位Linux内核中的汇编语言代码为什么使用汇编语言?C语言没有对应的硬件操作语言,如inb,outb等C语言没有对应的CPU特殊指令,如开关中断、寄存器操作等提高时间效率,如系统调用的陷入或返回提高空间效率,如系统第一扇区的引导程序由于Linux使用的编译器是GNU的gcc,所以源代码的汇编大多是GNU汇编语言GNU采用的汇编语言是一种介于386汇编语言和C语言之间的中间语言形式Linux源代码中汇编语言的使用形式完全汇编代码嵌在C语言程序的汇编片断几个用于引导的Intel格式的汇编语言程序AT&T格式的GNU汇编Linux操作系统分析Linux内核中的汇编语言代码为什么使用汇编语言?AT&T格GNU的x86汇编语言按UNIX领域的用户习惯,GNU使用了AT&T格式AT&T格式与Intel格式的区别(教材P22~23)Intel格式大多使用大写字母,而AT&T格式则都使用小写字母AT&T格式中寄存器名要加“%”前缀,而Intel格式则不用AT&T格式的源操作数在前,而Intel格式则是目标操作数据在前AT&T格式的命令用后缀b、w、l表示操作数精度,而Intel格式则用操作数前缀“BYTEPTR”、”WORDPRT”、”DWORDPRT”AT&T格式的直接操作数用$作前缀,而Intel格式则什么也不用AT&T格式的jump/call的目标地址前要加上*号,而Intel格式则不用Linux操作系统分析GNU的x86汇编语言按UNIX领域的用户习惯,GNU使用了嵌在C语言中的汇编语言要解决汇编中的寄存器和C语言中的变量结合的问题嵌在C语言中的386汇编语言程序段,一般由四部分构成(指令部:输出部:输入部:损坏部)指令部必须有,也就是汇编语言本身其中的寄存器的样板操作数%0,%1表示由gcc指定通用寄存器具体的寄存器前面就要加上两个%输出部,规定对目标操作数如何结合的约束条件输入部,规定对源操作数如何结合的约束条件损坏部,对可能损坏的用于中间结果的寄存器的说明gcc会在编译时自动加入保存所使用寄存器的语句,并在执行完汇编语句时将其恢复Linux操作系统分析嵌在C语言中的汇编语言要解决汇编中的寄存器和C语言中的变量结X86系列的寻址方式实地址模式寻址范围1MB(220),始用于16位的8086和8088用CS、DS、SS、ES解决数据地址总线与ALU宽度不一致问题有分段雏形,但不具备段的范围限长和特权级别等保护机制保护模式始于286,完善于386。继承了实模式下的16位寄存器直接寻址范围4GB(232),虚拟存储空间可达64TB(246)提供了实现分段和分页的虚拟存储的硬件机制是操作系统实现多进程存储管理以及提供存储保护的硬件基础Linux操作系统分析X86系列的寻址方式实地址模式Linux操作系统分析Linux的每个进程享有4GB的内存空间,0-3GB属于用户空间,3~4GB属于内核空间,内核空间对常规内存、I/O设备内存以及高端内存存在不同的处理方式。
Linux操作系统分析Linux的每个进程享有4GB的内存空间,0-3GB属于用如图3.4所示,Linux虚拟文件系统(VFS)隐藏各种了硬件的具体细节,为所有的设备提供了统一的接口。而且,它独立于各个具体的文件系统,是对各种文件系统的一个抽象,它使用超级块superblock存放文件系统相关信息,使用索引节点inode存放文件的物理信息,使用目录项dentry存放文件的逻辑信息。Linux操作系统分析如图3.4所示,Linux虚拟文件系统(VFS)隐藏各种X86的虚拟地址空间为了支持分段机制,x86把其虚拟地址空间分成大小不同的存储段逻辑地址(又称虚拟地址)指令中访问存储空间的地址称为逻辑地址,它由选段符寄存器(14bit)和段内偏移地址合并确定(32bit)逻辑地址空间(又称虚拟地址空间)逻辑地址空间是由逻辑地址所确定的内存访问空间,也就是x86的所有虚拟地址空间16K个段,每段最大4GB,逻辑地址空间共为64TB(246)Linux操作系统分析X86的虚拟地址空间为了支持分段机制,x86把其虚拟地址空间X86虚拟地址空间的划分x86把逻辑地址空间分成性质不同的两部分:全局地址空间。由系统中所有进程共享,通常存放操作系统资源和共享数据共8K个段,最大空间32TB局部地址空间。由各个进程自己使用,用于存储进程各自的代码和数据等。共8K个段,最大空间32TB划分依据段选择符寄存器的TI位全局地址空间和局部地址空间各占整个虚拟存储空间的一半,大小为32TBLinux操作系统分析X86虚拟地址空间的划分x86把逻辑地址空间分成性质不同的两选段符寄存器Linux操作系统分析选段符寄存器Linux操作系统分析分段机制将虚拟地址空间转换为线性地址空间为每个进程提供独立的4GB的线性地址空间为进程内的不同段提供不同的操作权限Linux操作系统分析分段机制将虚拟地址空间转换为线性地址空间Linux操作系统分X86的线性地址空间线性地址每个进程独自拥有的虚拟存储空间的地址X86的线性由段选择符寄存器所指向的段描述符中规定的基地址(32bit)和段内偏移地址相加确定(32bit)线性地址空间(又称进程空间)线性地址所确定的空间为每个进程能够自己独立使用的存储空间,称为线性地址空间,或进程空间X86的线性地址空间的大小为4G线性地址空间依然是虚拟存储空间操作系统的数据和代码被映射到所有进程的进程空间Linux操作系统分析X86的线性地址空间线性地址Linux操作系统分析X86线性地址空间的划分每个进程的线性地址空间被分成系统区(0级)用户区(3级)系统区,用于存放操作系统的代码、数据和各种全局数据结构。用户区,用于存放进程的代码、数据、堆栈以及进程的各种数据结构Linux操作系统分析X86线性地址空间的划分每个进程的线性地址空间被分成Linu分页机制分页机制把线性地址转换为物理地址把物理内存和每个进程的线性空间分成大小为4KB的页面实现两者之间页面的映射Linux操作系统分析分页机制分页机制把线性地址转换为物理地址Linux操作系统分x86的地址转换过程X86设置专门的存储管理单元(MMU)负责将CPU给出的虚拟地址转换为对应的物理地址Linux操作系统分析x86的地址转换过程X86设置专门的存储管理单元(MMU)负MMU的位置和功能X86的CPU使用的是虚拟地址Linux操作系统分析MMU的位置和功能X86的CPU使用的是虚拟地址Linux操MMU实现地址转换的过程Linux操作系统分析MMU实现地址转换的过程Linux操作系统分析段描述符分段机制中每个段的各种属性由段描述符(8Byte)来描述段描述符分为两种系统段描述符(s=0)用于特殊的系统段,如TSS描述符,LDT描述符等段描述符粒度位G是0,表明系统段以字节为单位系统段的最大空间为220个字节常规段描述符(s=1)用于程序的数据段和代码段如果段描述符粒度位G是1,表明常规段以页面为单位常规段的最大空间为220个页面Linux操作系统分析段描述符分段机制中每个段的各种属性由段描述符(8Byte)来访问权限与type的定义Linux操作系统分析访问权限与type的定义Linux操作系统分析段描述符表(DT)段描述符作为表项存储在段描述符表DTGDT,全局段存储在全局描述符表GDT由所有的进程共享,系统中只有一个GDTGDT的起始位置存放在寄存器GDTR,需要特权指令才能设置LDT,局部段存储在局部描述符表每个进程都有属于它的LDTLDT的起始位置存放在寄存器LDTR,需要特权指令才能设置段描述符表是特殊的段,所以系统的GDT和各个进程的LDT都存放在线性地址空间的特定区域内。Linux操作系统分析段描述符表(DT)段描述符作为表项存储在段描述符表DTLin全局描述符表(GDT)GDT中一般包括三种不同种类的描述符。系统内核代码段和数据段的描述符进程状态段(TSS)的描述符LDT描述符,偏移记录在TSS中GDT的最大空间为64KB,每个段描述符占8个字节,所以正好可以放下8K个全局段Linux操作系统分析全局描述符表(GDT)GDT中一般包括三种不同种类的描述符。GDTR寄存器GDTR存放GDT的起始位置,需要特权指令才能设置GDTR寄存器的长度为48位高32位表示基地址(线性地址)低16位表示GDT的大小Linux操作系统分析GDTR寄存器GDTR存放GDT的起始位置,需要特权指令才能局部描述符表LDT每个进程都有属于它的LDT每个LDT最大为216(64K)字节,每项大小为8字节。即每个进程最多有的8k(216÷8)个局部段第0段NULLdescriptor
第1段用户态代码段起始虚址0X00000000段长3G字节特权级3第2段用户态数据段起始虚址0X00000000段长3G字节特权级3Linux操作系统分析局部描述符表LDT每个进程都有属于它的LDT第0段NULLLDTR寄存器LDTR寄存器的长度为64位高16位存储当前进程的LDT的描述符在GDT中的位置可通过特权指令设置后48位为高速缓存,其中高32位表示基地址,低16位表示LDT的大小Linux操作系统分析LDTR寄存器LDTR寄存器的长度为64位Linux操作系统由LDTR确定LDT地址的过程Linux操作系统分析由LDTR确定LDT地址的过程Linux操作系统分析分段机制中地址的转换分段机制中地址的转换过程与实模式相同,首先根据指令性质来确定应该使用哪一个段寄存器根据段寄存器的内容,找到相应的“地址段描述结构”从地址段描述结构中得到基地址将指令中发出的地址作为位移,与段描述结构中规定的段长度相比,检查是否越界根据指令的性质和段描述符中的访问权限来确定是否越权将指令中发出的地址作为位移,与基地址相加而得出实际的“物理地址”(线性地址)使用与寄存器对应的“影子”结构缓存相应的段描述符增加安全性加快地址转换速度Linux操作系统分析分段机制中地址的转换分段机制中地址的转换过程Linux操作系带有高速缓存的选段符寄存器Linux操作系统分析带有高速缓存的选段符寄存器Linux操作系统分析x86的平面地址相对于“段寄存器/偏移量”的“层次”结构,符合以下条件的地址称为“平面(flat)地址”每个段描述符的基地址设为0每个段的长度设置为最大(4GB)Linux的内存管理采用平面地址,这是由gcc编译器决定的平面地址并没有绕过段描述符、段寄存器这样的段式内存管理机制,而只是这一机制的一个应用特例Linux操作系统分析x86的平面地址相对于“段寄存器/偏移量”的“层次”结构,符分页机制分页机制把线性地址转换为物理地址把物理内存和每个进程的线性空间被划分成分成大小为4KB的页面,每个页面的高20位为页面序号,起始地址的低12位为0为了程序能够运行,为线性空间的页面在物理内存中找一物理页面对应,并记录其页面序号之间的对应关系相互对应两页面的页内地址偏移(低12位地址)相同进程的线性空间的分页每个进程4GB的线性地址空间可划分成1M个页面物理内存的分页根据物理内存的实际大小划分成若干个页面Linux操作系统分析分页机制分页机制把线性地址转换为物理地址Linux操作系统分控制寄存器(CR)组Linux操作系统分析控制寄存器(CR)组Linux操作系统分析线性空间的两级分组4GB直接分成4KB需要页表有1M个表项两级分组首先将4GB空间划分成1K个4MB的块,由页表目录描述再将每个4MB的块划分成1K个4KB的页,由页表描述32位的线性地址被划分成三部分页表目录偏移地址(10bit),即块号
页表偏移地址(10bit),即块中的页号页内偏移地址(12bit)线性空间页号Linux操作系统分析线性空间的两级分组4GB直接分成4KB需要页表有1M个表项线两级页表结构页表目录和页表都必需保存在物理地址空间页表目录表、页表和页面的大小均为4KB每个页表目录表和页表各有1024个表项Linux操作系统分析两级页表结构页表目录和页表都必需保存在物理地址空间Linux页表目录表每个进程设置一个页表目录表包括1024个表项。每个表项是4字节,指向一个页表页表目录表大小为4KB页表目录表的表项结构
Linux操作系统分析页表目录表每个进程设置一个页表目录表Linux操作系统分页表每进程最多可有1024个页表每个页表有1024表项,每个表项的长度是4字节,指向一个物理页面每个页表的大小为4KB页表的表项结构AVL供操作系统自行定义使用。A访问位A=1表示页表或页面已被访问过,U/S用户/系统访问权限位U/S=1表示用户访问级,U/S=0表示系统访问级。W/R读/写保护位,W/R=1表示允许写入和读取,W/R=0表示不允许写入,仅允许读取。D修改位D=1表示该页面已被修改过,P存在位,P=1表示该页表或页面在物理存储器中,Linux操作系统分析页表每进程最多可有1024个页表Linux操作系统分析线性地址到物理地址的转换Linux操作系统分析线性地址到物理地址的转换Linux操作系统分析页面高速缓存寄存器为了降低页目录和页表的查询次数而设置缓存32项CPU最近使用的线性页面对应的物理页面号,平均可达98%的命中率。Linux操作系统分析页面高速缓存寄存器为了降低页目录和页表的查询次数而设置Linx86的多任务机制为了使CPU可以快速地从一个任务切换到另一个任务,x86设置了任务状态段TSS存储CPU管理一个任务时所需的各种信息任务寄存器TR对过指向TSS来快速确定当前执行的任务有16位的可见部分,表示TSS在GDT中的偏移有不可见部分,缓存当前TSS的基地址和限长Linux操作系统分析x86的多任务机制为了使CPU可以快速地从一个任务切换到另一任务状态段TSS的内容Linux操作系统分析任务状态段TSS的内容Linux操作系统分析Linux设备驱动入门Linux操作系统分析Linux设备驱动入门Linux操作系统分析Linux操作系统分析Linux操作系统分析Linux操作系统分析Linux操作系统分析Linux操作系统分析Linux操作系统分析Linux操作系统分析Linux操作系统分析网络接口提供了对各种网络的标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序,网络协议部分负责实现每一种可能的网络传输协议,网络设备驱动程序负责与硬件设备进行通信,每一种可能的硬件设备都有相应的设备驱动程序。Linux操作系统分析网络接口提供了对各种网络的标准的存取和各种网络硬件的支持。网Linux操作系统分析Linux操作系统分析Linux内核分析
TheAnalysisoftheLinuxKernelLinux操作系统分析Linux内核分析
TheAnalysisofthe教材Linux内核源代码情景分析毛德操
胡希明著浙江大学出版社2001年9月第1版
Linux操作系统分析教材Linux内核源代码情景分析Linux操作系统分析参考书目LinuxKernel中文版,DavidARusling著Linux内核完全注释,赵炯著,,2003年1.2.2修正版Linux内核2.4版源代码分析大全,李善平等著,机械工业出版社,2002年1月第1版UNIX操作系统设计,MJBach著,机械工业出版社,2001年现代操作系统[英文],AndrewS.Tanenbaum著,机械工业出版社,2002年动手写自己的操作系统,于渊编著,电子工业出版社,2005年8月Linux操作系统分析参考书目LinuxKernel中文版,DavidAR本课程需要的基础知识具备操作系统的基础知识具备C语言程序设计的基础知识粗通汇编语言编程熟悉UNIX用户界面,略知微机系统结构,尤其是保护模式,分段、分页机制。Linux操作系统分析本课程需要的基础知识具备操作系统的基础知识Linux操作系统第一章预备知识本章主要内容Linux内核的基础知识为什么分析操作系统?为个么选择Linux?Linux和Linux内核的关系Linux的技术特点Linux内核的组成结构及版本Linux源代码的分析方法、工具其他相关基础知识Linux内核源代码中的C语言代码的特点Linux内核源代码中的汇编语言代码的特点x86的虚拟存储技术Linux操作系统分析第一章预备知识本章主要内容Linux操作系统分析为什么分析操作系统?分析操作系统的目的深入理解一个操作系统的内在机制及其实现机理学习系统软件的设计方法和实现技巧研究和分析制约操作系统性能的原因不同于学习操作系统的使用普通用户学习通过操作界面使用操作系统程序设计者学习通过系统调用使用操作系统操作系统的设计目的就是为上述两类用户提供统一的使用方式Linux操作系统分析为什么分析操作系统?分析操作系统的目的Linux操作系统分析为什么选择分析Linux?从其发展历史看,它属于现在得到广泛应用的UNIX家族,并已被大量用户认可和接受集中了全世界众多操作系统黑客的技术精华在嵌入式和实时操作系统方面有大量的社会需求源代码开放,容易获取并学习未来24个月嵌入式操作系统的应用调查(2000.9)
Linux操作系统分析为什么选择分析Linux?从其发展历史看,它属于现在得到广泛Linux内核的组成存储管理进程管理设备管理文件系统进程间通信网络Linux操作系统分析Linux内核的组成存储管理Linux操作系统分析Linux的内核结构图Linux操作系统分析Linux的内核结构图Linux操作系统分析Linux内核源代码目录结构(1)arch这个子目录包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是x86。include这个目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。init此目录包含核心启动代码。mm此目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下,如对应于X86的就是arch/x86/mm/fault.c。drivers系统中所有的设备驱动都位于此目录中。它又进一步划分成几类设备驱动,每一种也有对应的子目录,如声卡的驱动对应于drivers/sound。ipc此目录包含了核心的进程间通讯代码。Linux操作系统分析Linux内核源代码目录结构(1)arch这个子目录包含了Linux内核源代码目录结构(2)modules此目录包含已建好可动态加载的模块。fsLinux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext2文件系统对应的就是ext2子目录。kernel主要核心代码。同时与处理器结构相关代码都放在arch/*/kernel目录下。net核心的网络部分代码。里面的每个子目录对应于网络的一个方面。lib此目录包含了核心的库代码。与处理器结构相关库代码被放在arch/*/lib/目录下。scripts此目录包含用于配置核心的脚本文件。Documentation此目录是一些文档,起参考作用。Linux操作系统分析Linux内核源代码目录结构(2)modules此目录包含Linux内核源代码的获取方式商业发行版本附带的发行版内核,通常不是最新的官方网站:中国自由软件库(最新版)发行商网站大学网站/Linux/kernelN/OS/Linux/kernelLinux操作系统分析Linux内核源代码的获取方式商业发行版本附带的发行版内核,Linux源代码的阅读方法和工具(1)Linux源代码的阅读方法阅读顺序纵向,就是顺着程序的执行顺序逐步进行横向,就是分模块进行划分不绝对的,而是经常结合在一起进行Linux的启动的代码就可以顺着linux的启动顺序一步一步地读,大致流程如下(以X86平台为例):./arch/x86/boot/bootSect.S./arch/x86/boot/setup.S./arch/x86/kernel/head.S./init/main.c中的start_kernel()对于内存管理等部分,可以单独拿出来按模块进行阅读分析。Linux操作系统分析Linux源代码的阅读方法和工具(1)Linux源代码的阅读Linux操作系统分析Linux操作系统分析Linux源代码的阅读方法和工具(2)windows环境下利用SourceInsight阅读工具可从/上边下载30天试用版本linux环境下利用lxr(linuxcrossreference)或glimpse等阅读工具进行阅读建议开始最好按顺序阅读启动代码然后进行专题阅读,如进程部分,内存管理部分等。在每个功能函数内部应该一步步来实际上这是一个反复的过程,不可能读一遍就理解Linux操作系统分析Linux源代码的阅读方法和工具(2)windows环境下利SourceInsight软件使用方法选择Project菜单下的new,新建一个工程,输入工程名把欲读的源代码加入(可以整个目录加)后,该软件就分析你所加的源代码。分析完后,就可以进行阅读了。打开相要阅读的文件如果想看某一变量的定义先把光标定位于该变量然后点击工具条上的相应选项或从右键菜单中选择该变量的定义就显示出来对于函数的定义与实现也可以同样操作Linux操作系统分析SourceInsight软件使用方法选择Project菜Linux内核源代码的C语言代码(1)内核的主体是以GNU的C语言编写的,GNU对C语言本身在ANSIC的基础上作了不少扩充使用gcc作为编译工具,gcc同时又是C++编译工具内核具有很多C++语言的特点gcc从C++语言中吸收了inline和const比define更安全,如可定义数据类型等等内核的版本与gcc的版本间有依赖关系Longlongint,用于支持64位的CPU结构为了防止扩展的属性和保留字与变量名的冲突“__保留字__”等价于“保留字”attribute__((属性)),如aligned,packedLinux操作系统分析Linux内核源代码的C语言代码(1)内核的主体是以GNU的Gcc从C++语言中吸收了“inline”和“const”。其实,GNU的C和C++是合为一体的,gcc既是C编译又是C++编译,所以从C++中吸收一些东西到C中是很自然的。从功能上说,inline函数的使用与#define宏定义相似,但更有相对的独立性,也更安全。使用inline函数也有利于程序调试。如果编译时不加优化,则这些inline函数就是普通的,独立的函数,更便于调试。调试好以后,再采用优化重新编译一次,这些inline函数就像宏操作一样融入了引用处的代码中,有利于提高运行效率。由于inline函数的大量使用,相当一部分代码从.c文件移入了.h文件中。Linux操作系统分析Gcc从C++语言中吸收了“inline”和“cLinux内核源代码的C语言代码(2)Do{…}while(0)的作用使{}之间的代码构成一个块执行空操作,如为进程切换作准备举例如果没有Do{…}while(0)Linux操作系统分析Linux内核源代码的C语言代码(2)Do{…}whileLinux内核源代码的C语言代码(3)双链数据结构使得针对这些队列的操作可用于不同数据结构宿主数据结构举例Linux操作系统分析Linux内核源代码的C语言代码(3)双链数据结构LinuxLinux内核源代码的C语言代码(4)宿主结构起始地址的定位举例当前结构中list的地址–当page结构刚好位于地址0时的list地址Linux操作系统分析Linux内核源代码的C语言代码(4)宿主结构起始地址的定位Linux内核中的汇编语言代码为什么使用汇编语言?C语言没有对应的硬件操作语言,如inb,outb等C语言没有对应的CPU特殊指令,如开关中断、寄存器操作等提高时间效率,如系统调用的陷入或返回提高空间效率,如系统第一扇区的引导程序由于Linux使用的编译器是GNU的gcc,所以源代码的汇编大多是GNU汇编语言GNU采用的汇编语言是一种介于386汇编语言和C语言之间的中间语言形式Linux源代码中汇编语言的使用形式完全汇编代码嵌在C语言程序的汇编片断几个用于引导的Intel格式的汇编语言程序AT&T格式的GNU汇编Linux操作系统分析Linux内核中的汇编语言代码为什么使用汇编语言?AT&T格GNU的x86汇编语言按UNIX领域的用户习惯,GNU使用了AT&T格式AT&T格式与Intel格式的区别(教材P22~23)Intel格式大多使用大写字母,而AT&T格式则都使用小写字母AT&T格式中寄存器名要加“%”前缀,而Intel格式则不用AT&T格式的源操作数在前,而Intel格式则是目标操作数据在前AT&T格式的命令用后缀b、w、l表示操作数精度,而Intel格式则用操作数前缀“BYTEPTR”、”WORDPRT”、”DWORDPRT”AT&T格式的直接操作数用$作前缀,而Intel格式则什么也不用AT&T格式的jump/call的目标地址前要加上*号,而Intel格式则不用Linux操作系统分析GNU的x86汇编语言按UNIX领域的用户习惯,GNU使用了嵌在C语言中的汇编语言要解决汇编中的寄存器和C语言中的变量结合的问题嵌在C语言中的386汇编语言程序段,一般由四部分构成(指令部:输出部:输入部:损坏部)指令部必须有,也就是汇编语言本身其中的寄存器的样板操作数%0,%1表示由gcc指定通用寄存器具体的寄存器前面就要加上两个%输出部,规定对目标操作数如何结合的约束条件输入部,规定对源操作数如何结合的约束条件损坏部,对可能损坏的用于中间结果的寄存器的说明gcc会在编译时自动加入保存所使用寄存器的语句,并在执行完汇编语句时将其恢复Linux操作系统分析嵌在C语言中的汇编语言要解决汇编中的寄存器和C语言中的变量结X86系列的寻址方式实地址模式寻址范围1MB(220),始用于16位的8086和8088用CS、DS、SS、ES解决数据地址总线与ALU宽度不一致问题有分段雏形,但不具备段的范围限长和特权级别等保护机制保护模式始于286,完善于386。继承了实模式下的16位寄存器直接寻址范围4GB(232),虚拟存储空间可达64TB(246)提供了实现分段和分页的虚拟存储的硬件机制是操作系统实现多进程存储管理以及提供存储保护的硬件基础Linux操作系统分析X86系列的寻址方式实地址模式Linux操作系统分析Linux的每个进程享有4GB的内存空间,0-3GB属于用户空间,3~4GB属于内核空间,内核空间对常规内存、I/O设备内存以及高端内存存在不同的处理方式。
Linux操作系统分析Linux的每个进程享有4GB的内存空间,0-3GB属于用如图3.4所示,Linux虚拟文件系统(VFS)隐藏各种了硬件的具体细节,为所有的设备提供了统一的接口。而且,它独立于各个具体的文件系统,是对各种文件系统的一个抽象,它使用超级块superblock存放文件系统相关信息,使用索引节点inode存放文件的物理信息,使用目录项dentry存放文件的逻辑信息。Linux操作系统分析如图3.4所示,Linux虚拟文件系统(VFS)隐藏各种X86的虚拟地址空间为了支持分段机制,x86把其虚拟地址空间分成大小不同的存储段逻辑地址(又称虚拟地址)指令中访问存储空间的地址称为逻辑地址,它由选段符寄存器(14bit)和段内偏移地址合并确定(32bit)逻辑地址空间(又称虚拟地址空间)逻辑地址空间是由逻辑地址所确定的内存访问空间,也就是x86的所有虚拟地址空间16K个段,每段最大4GB,逻辑地址空间共为64TB(246)Linux操作系统分析X86的虚拟地址空间为了支持分段机制,x86把其虚拟地址空间X86虚拟地址空间的划分x86把逻辑地址空间分成性质不同的两部分:全局地址空间。由系统中所有进程共享,通常存放操作系统资源和共享数据共8K个段,最大空间32TB局部地址空间。由各个进程自己使用,用于存储进程各自的代码和数据等。共8K个段,最大空间32TB划分依据段选择符寄存器的TI位全局地址空间和局部地址空间各占整个虚拟存储空间的一半,大小为32TBLinux操作系统分析X86虚拟地址空间的划分x86把逻辑地址空间分成性质不同的两选段符寄存器Linux操作系统分析选段符寄存器Linux操作系统分析分段机制将虚拟地址空间转换为线性地址空间为每个进程提供独立的4GB的线性地址空间为进程内的不同段提供不同的操作权限Linux操作系统分析分段机制将虚拟地址空间转换为线性地址空间Linux操作系统分X86的线性地址空间线性地址每个进程独自拥有的虚拟存储空间的地址X86的线性由段选择符寄存器所指向的段描述符中规定的基地址(32bit)和段内偏移地址相加确定(32bit)线性地址空间(又称进程空间)线性地址所确定的空间为每个进程能够自己独立使用的存储空间,称为线性地址空间,或进程空间X86的线性地址空间的大小为4G线性地址空间依然是虚拟存储空间操作系统的数据和代码被映射到所有进程的进程空间Linux操作系统分析X86的线性地址空间线性地址Linux操作系统分析X86线性地址空间的划分每个进程的线性地址空间被分成系统区(0级)用户区(3级)系统区,用于存放操作系统的代码、数据和各种全局数据结构。用户区,用于存放进程的代码、数据、堆栈以及进程的各种数据结构Linux操作系统分析X86线性地址空间的划分每个进程的线性地址空间被分成Linu分页机制分页机制把线性地址转换为物理地址把物理内存和每个进程的线性空间分成大小为4KB的页面实现两者之间页面的映射Linux操作系统分析分页机制分页机制把线性地址转换为物理地址Linux操作系统分x86的地址转换过程X86设置专门的存储管理单元(MMU)负责将CPU给出的虚拟地址转换为对应的物理地址Linux操作系统分析x86的地址转换过程X86设置专门的存储管理单元(MMU)负MMU的位置和功能X86的CPU使用的是虚拟地址Linux操作系统分析MMU的位置和功能X86的CPU使用的是虚拟地址Linux操MMU实现地址转换的过程Linux操作系统分析MMU实现地址转换的过程Linux操作系统分析段描述符分段机制中每个段的各种属性由段描述符(8Byte)来描述段描述符分为两种系统段描述符(s=0)用于特殊的系统段,如TSS描述符,LDT描述符等段描述符粒度位G是0,表明系统段以字节为单位系统段的最大空间为220个字节常规段描述符(s=1)用于程序的数据段和代码段如果段描述符粒度位G是1,表明常规段以页面为单位常规段的最大空间为220个页面Linux操作系统分析段描述符分段机制中每个段的各种属性由段描述符(8Byte)来访问权限与type的定义Linux操作系统分析访问权限与type的定义Linux操作系统分析段描述符表(DT)段描述符作为表项存储在段描述符表DTGDT,全局段存储在全局描述符表GDT由所有的进程共享,系统中只有一个GDTGDT的起始位置存放在寄存器GDTR,需要特权指令才能设置LDT,局部段存储在局部描述符表每个进程都有属于它的LDTLDT的起始位置存放在寄存器LDTR,需要特权指令才能设置段描述符表是特殊的段,所以系统的GDT和各个进程的LDT都存放在线性地址空间的特定区域内。Linux操作系统分析段描述符表(DT)段描述符作为表项存储在段描述符表DTLin全局描述符表(GDT)GDT中一般包括三种不同种类的描述符。系统内核代码段和数据段的描述符进程状态段(TSS)的描述符LDT描述符,偏移记录在TSS中GDT的最大空间为64KB,每个段描述符占8个字节,所以正好可以放下8K个全局段Linux操作系统分析全局描述符表(GDT)GDT中一般包括三种不同种类的描述符。GDTR寄存器GDTR存放GDT的起始位置,需要特权指令才能设置GDTR寄存器的长度为48位高32位表示基地址(线性地址)低16位表示GDT的大小Linux操作系统分析GDTR寄存器GDTR存放GDT的起始位置,需要特权指令才能局部描述符表LDT每个进程都有属于它的LDT每个LDT最大为216(64K)字节,每项大小为8字节。即每个进程最多有的8k(216÷8)个局部段第0段NULLdescriptor
第1段用户态代码段起始虚址0X00000000段长3G字节特权级3第2段用户态数据段起始虚址0X00000000段长3G字节特权级3Linux操作系统分析局部描述符表LDT每个进程都有属于它的LDT第0段NULLLDTR寄存器LDTR寄存器的长度为64位高16位存储当前进程的LDT的描述符在GDT中的位置可通过特权指令设置后48位为高速缓存,其中高32位表示基地址,低16位表示LDT的大小Linux操作系统分析LDTR寄存器LDTR寄存器的长度为64位Linux操作系统由LDTR确定LDT地址的过程Linux操作系统分析由LDTR确定LDT地址的过程Linux操作系统分析分段机制中地址的转换分段机制中地址的转换过程与实模式相同,首先根据指令性质来确定应该使用哪一个段寄存器根据段寄存器的内容,找到相应的“地址段描述结构”从地址段描述结构中得到基地址将指令中发出的地址作为位移,与段描述结构中规定的段长度相比,检查是否越界根据指令的性质和段描述符中的访问权限来确定是否越权将指令中发出的地址作为位移,与基地址相加而得出实际的“物理地址”(线性地址)使用与寄存器对应的“影子”结构缓存相应的段描述符
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 学生共青团活动介绍
- 太阳能发电效益测算
- 总结者挑剔者控场者记录者无领导小组讨论测评常见的角
- 100以内加减法竖式计算单元作业试题大全附答案
- 需要性重要性创造性可行性合适性
- 《生理学感觉系统》课件
- 《入井安全须知》课件
- 一提供安全感
- f放射治疗总体概况
- 公司培训介绍
- 2024 ESC慢性冠脉综合征指南解读(全)
- 2024二十届三中全会知识竞赛题库及答案
- (高清版)JTG 5142-2019 公路沥青路面养护技术规范
- 物流运输项目 投标方案(适用烟草、煤炭、化肥、橡胶等运输项目)(技术方案)
- 电力企业合规培训课件
- 领导干部任前谈话记录表
- GB/T 10058-2009电梯技术条件
- 施工现场质量管理检查记录表【精选文档】
- 新版pep小学英语四上单词默写
- 期中考试班会PPT
- 送货单EXCEL模板
评论
0/150
提交评论