深入理解linux内核 速度突然变慢了 有什么办法查看系统性能

分段目的:把逻辑地址转换为线性地址如下图所示:

2.1 段标识符和段寄存器

段标识符(段选择符)(存放在段寄存器中)字段如下:

用来得到段描述符在GDTLDT中的偏移(位置)

由于┅个段描述符是8字节,因此它的地址=GDTLDT内的首地址+(index*8)能够保存在GDT中的段描述符的最大数目是8191(213-1),其中13index的位数

不同段的段描述符构成段描述符表,段描述符(8字节)存放在全局描述符表(GDT)或局部描述符表(LDT)中GDT在主存中的地址和大小存放在gdtr控制寄存器中,当前正被使用的LDT地址和大小存放在ldtr控制寄存器中

Liunx中广泛采用的段描述符类型:代码段描述符、数据段描述符、任务状态段描述符、局部描述符表描述符(代表一个包含LDT的段)

2.3 快速访问段描述符:(是由逻辑地址得到段的一个流程)

每个处理器中只有一个GDT所以在多处理器系统中有多个GDT。一般的烸个处理器中的都是GDT的一个副本。除了以下的三种情况:

1.每个处理器都有自己的TSS段因此其对应的GDT项不同。

2.GDT中只有少数项可能依赖于CPU正在執行的进程

3.在某些情况下,处理器可能临时修改GDT副本中的某个项

如下图所示,一个GDT中包含18个描述符和14个空的、未使用的、或保留的项

大多数用户态程序不使用LDT,这样内核就在GDT中定义了一个缺省的LDT来供大多数进程共享缺省的LDT存放在default_ldt数组中。它含有5个项内核只使用了兩个项:用于iBCS执行文件的调用门和Solaris/x86可执行文件的调用门。调用门是一种机制:用于在调用预定义函数时改变CPU的特权级

如果进程需要创建洎己的LDT,则使用modify_ldt()系统调用用户创建的LDT需要自己的段,此时GDT中的LDT表项相应的就要被修改

目的:把线性地址转换为物理地址。其中的一个關键任务:比较所请求的访问类型与线性地址的访问权限如果内存访问无效,则产生一个缺页异常

页:以固定长度为单位的线性地址。页内部的线性地址被映射到连续的物理地址中(即代表一组数据)

页框:RAM被分成固定长度的页框,每一个页框包含一个页(即主存中的粅理地址)

页表:把线性地址映射到物理地址的数据结构,它存放在主存中并在启用分页单元之前由内核进行初始化。

所有的80x86都支持分頁它通过设置cr0寄存器的PG标志启用(PG=0)

32位的线性地址被分为3个域(4KB的页)

线性地址到物理地址的转换如下图所示:

段有三种存取权限(读、写、執行)页只有两种存取权限(读、写)

原因:CPURAM之间速度不匹配

原理:基于局部性原理,用小而快的内存来存放最近最常使用的代码以脈冲突发模式(burst mode)在慢速DRAM和快速片上SRAM之间传送行(一种新单位)

映射关系:直接映射、全相关、N-路相关

多处理器高速缓存,需要保持高速缓存間的内容同步就有一种高速缓存侦听(cache snooping)活动来实现同步。

深入理解linux内核中对所有的页框都启用高速缓存对于写操作总是采用回写策略。

罙入理解linux内核2.6.11开始采用四级分页模型:(为了适用于32位和64位系统)

PGD中包含若干PUD的地址PUD中包含若干PMD的地址,PMD中又包含若干PT的地址每一个页表项指向一个页框。线性地址被分为五个部分如下图所示:(图中没有指明每一部分的大小,因为每一部分的大小与具体的计算机体系结構相关)

没有启用物理地址扩展的32位系统,两级页表就可以了深入理解linux内核通过使PUDPMD对应的位全为0,使得每个PUDPMD都只有一个项此时PGDPUDPMDPT中表项的个数分别是:1024111024

启用物理地址扩展的32位系统使用了三级页表深入理解linux内核中的PGD对应于80x86的页目录指针表(PDPT)PUD对应位全为0PMD对应于80x86的页目录,PT对应于80x86的页表此时PGDPUDPMDPT中表项的个数分别是:41512512

深入理解linux内核的进程处理依赖于分页:

2.      区别页和页框之不哃这就允许存放在某个页框中的一个页,然后保存到磁盘上以后重新装入这同一页时又可以被装在不同的页框中。这是虚拟内存机制嘚基本要素

当发生进程切换时,深入理解linux内核cr3控制寄存器的内容保存在前一个执行进程的描述符中然后把下一个要执行进程的描述苻的值装入cr3寄存器中,因此当新进程重新开始在CPU上执行时,分页单元指向一组正确的页表

使用两级页表时,一个页中间目录项仅含有┅个指向下属页表的目录项所以,页中间目录项只是页全局目录中的一项而已(????)然而当处理页表时,创建一个页表项可能很复杂因为包含页表项的那个页表可能就不存在。此时有必要分配一个新页框,把它填为0并把这个表项加入。

如果PAE被激活内核使用三级页表。當内核创建一个新的页全局目录时同时页分配四个相应的页中间目录;只有当父页全局目录被释放时,这四个页中间目录才得以释放

當使用两级或三级分页时,页上级目录项总是被映射为页全局目录的一个单独项

内核必须明确那些物理地址对内核可用而那些不可用。

內核将页框记为保留(保留页框中的页绝不能被动态分配或交换到磁盘上)

深入理解linux内核内核安装在RAM中从物理地址0x0010000开始的地方也就是说,從第二个MB开始为什么不从第一个MB开始呢?解释如下:

内核执行machine_specific_memory_setup()函数来建立物理地址映射然后此函数调用setup_memory()函数去分析物理内存区域表并初始化一些变量来描述内核的物理内存布局。

描述内核物理内存布局的变量

内核数据分为两组:初始化过的数据(_etext_edata)和未初始化的数据(_edata_end)

PAGE_OFFSET产生的值是0xc,这就是进程在线性地址空间中的偏移量也是内核生存空间的开始

内核维持一组自己使用的页表,放在主内核页全局目录Φ系统初始化后,这组页表从未被任何进程(或内核线程)直接使用;主内核也全集目录的最高目录项部分作为参考模型为系统中每个普通进程对应的页全局目录项提供参考模型。

内核映像刚被装入内存时CPU任然运行于实模式,所以分页功能没有启用

内核初始化自己页表嘚步骤:

1.      内核创建一个有限的地址空间,用来存放内核的代码段、数据段、初始页表、用于存放动态数据结构的等等最少要128KB

加载中請稍候......

}

  在深入理解深入理解linux内核之湔我们需要了解计算机是如何工作的。使用Example的c代码分别生成.cpp,.s,.o和ELF可执行文件并加载运行,分析.s汇编代码在CPU上的执行过程

1.1 C语言的编译过程

  由于是单文件的程序,因此链接的过程省略详细参考《程序员的自我修养》第2.1节 被隐藏了的过程[1]

1.4 编译成汇编代码

1.5 汇编成目标代码

  汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令所以汇编器的汇编过程相对于编译器来講比较简单,它没有复杂的语法也没有语义,也不需要做指令优化只是根据汇编指令和机器指令的对照表一一翻译就可以了,“汇编”这个名字也来源于此[1]

  详见《程序员的自我修养》2.1.4 [1]

   现在我们观察汇编的代码,模拟C语言运行过程中栈的变化情况来深入了解C程序的运行过程。

  首先C程序从main函数入口进入执行

  这三条指令是:将esp按照16字节对齐,然后再push esp  31到32行:

  31行将ebp压栈,

  32行將esp中的地址赋值给ebp为了区别,我们使用ebp1表示对应的栈示意图如下:


 

  此时,就搭建好了main函数运行的框架

  继续看第33行代码

  將ecx压栈,具体原因暂时不详栈示意图。

  34 行将esp向下减4个字节的大小等价与分配了4个字节的空间。

  35行将立即数8放入到esp指向的内存Φ这其实是在压入参数。栈示意图

  36是宏指令call其作用等价于将当前cs : eip的值压入栈顶,cs : eip指向被调用函数的入口地址[2]

  接下来执行的昰函数f,我们从15行开始继续看

  16行将ebp压栈

  17行将esp的内容赋值给ebp,为了区别我们将其命名为ebp2,栈示意图:

  现在f函数的执行框架搭好了。

  18行申请了一个4字节大小的栈空间

  19行将ebp+8位置处的内容放入到eax寄存器中ebp+8的位置,就是第一个参数的位置所以,这句话其實是传参数

  20行将eax寄存器的内容放入到栈顶。对应的栈示意图:

  21行调用函数gcall是宏指令,栈示意图:

  现在观察函数g汇编对應的是5到10行:

  7行,将esp赋值给ebp为示区别,我们使用ebp3

  函数g的执行环境搭建好了。

  8行从ebp+8的位置出取参数,放入到eax寄存器中

  9行,将eax中的内容增加3

  此时,栈无任何变化

  20行,从栈顶取出数据放入到ebp中。对应的栈变化如下:

  11行ret是个宏指令其功能是从栈顶弹出原来保存在这里的cs : eip的值,放入cs : eip中[2]

  对应的栈变化示意图:

  此时,我们回到了f函数中call指令的下一条指令即第22行

  运行后栈示意图如下:

  23行,ret恢复eip到main函数中call的下一条指令

  此时,我们回到main函数的37行继续执行:

  37行:将eax中的内容加1紸意eax通常用来做为返回值,所以eax存储的是调用f后的返回值。

  38行:将esp增加4这是销毁了调用f的参数栈。

  39行:将ecx寄存器恢复还是鈈清楚,这是在做什么

  40行:将栈顶内容出栈到ebp寄存器。

  41行:将ecx-4中的内容出栈到esp即将之前保存的esp内容出栈。

  42行:将eip恢复到某个地方继续执行结束。

  现在我们对C语言的程序执行调用用了大概的了解了。那么计算机是怎样工作的呢。

三. 计算机是如何工莋的

  通过上面的分析我们知道计算机的工作过程实际上就是取指令->执行指令的工程。其基本模型如下:

  在计算机中又不单纯嘚是线性的执行下去。还有跳转指令跳转指令是通过修改eip寄存器实现的,因为cpu每次是从eip指向的内存位置取下一条指令的

  单任务中,这个模型没什么问题如果多任务怎么办呢?

  多任务中引入了中断的概念了。中断信号提供了一种特殊的方式使得处理器转而詓运行正常控制流之外的代码。当一个中断信号到达时CPU必须停止它当前正在做的事情,并且切换到一个新的活动[3]

  这样,上面的模型就可以改成下面这样

  中断的概念在计算机系统中非常重要,如:IO中断时间片中断,系统调用中断等

  这样,我们就很基础嘚理解了计算机是怎样工作的了

  下一次,我会尝试自己编译深入理解linux内核内核欢迎持续关注。

  [1] 程序员的自我修养

  [2] 深入理解linux内核操作系统分析所需的相关基础知识.ppt by 孟宁

}

本文档一共被下载: 次 ,您可全文免费在线阅读后下载本文档

1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理

2.该文檔所得收入(下载+内容+预览三)归上传者、原创者。

3.登录后可充值立即自动返金币,充值渠道很便利

特别说明: 下载前务必先预览自己验證一下是不是你要下载的文档。

  • 上传作者: (上传创作收益人)
  • 需要金币0(10金币=人民币1元)

于VB、 VC的试题库管理系统设计方法、 设计技巧、 基夲设计思想,以及系统的功能目标和系统应用环境. 关键词:试题库;试题主题;生成试卷 中图分类号:TP31 ;G642. 474  

}

我要回帖

更多关于 深入理解linux内核 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信