`
tomhibolu
  • 浏览: 1413639 次
文章分类
社区版块
存档分类
最新评论

kernel hacker修炼之道之内存管理-分段

 
阅读更多
<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

浅析linux内核内存管理之分段

作者:李万鹏

<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

硬件中的分段:


逻辑地址(logicaladdress)

包含在机器语言中用来指定一个操作数或一条指令的地址。每一个逻辑地址都由一个段(segment)和偏移量(offset)组成,偏移量指明了从段开始的地方到实际地址之间的距离。

线性地址(linearaddress)(也称为虚拟地址)

是一个32位无符号整数,可以用来表示高达4GB的地址,范围从0x000000000xffffffff

物理地址(physicaladdress)

用于内存芯片级内存单元的寻址。


内存单元控制(MMU)通过一种称为分段单元(segmentationunit)的硬件电路把一个逻辑地址转换成线性地址;第二个称为分页单元(pagingfault)的硬件电路把线性地址转换成一个物理地址。

<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

段选择符和段寄存器:


<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

一个逻辑地址由两部分组成:段标识符+偏移量。段标识符是一个16位长的字段,称为段选择符,而偏移量是一个32位长的字段。段选择符的3~15位指定了描述符在gdt或ldt中的位置,第2位指明是在gdt中还是在ldt中,0~1为RPL(requestprivilegelevel),指定特权级,linux只用0级(内核态)和3级(用户态)。所以,如果是访问代码段,RPL位为0,则访问kernelcode,RPL位为1,则访问datacode。为了快速找到段选择符,处理器提供段寄存器,段寄存器的唯一目的是存放段选择符。一共6个段寄存器:cs,ss,ds,es,fs和gs。其中cs(代码段寄存器)还有一个很重要的功能:它含有一个两位的字段,用以指明CPU的当前特权级(CPL)。值为0代表最高优先级,而值为3代表最低优先级。


<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

下面来看一下段描述符:

每一个段描述符由8个字节组成。其中BASE字段指明了段的起始位置的线性地址,LIMIT字段指定了段的长度,单位是段占用的页的个数。


<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

Linux中的分段:


与分段相比,linux更喜欢使用分页方式,因为:

  • 当所有的进程使用相同的段寄存器值时,内存管理变得简单,也就是说他们能够共享同样的一组线性地址。

  • Linux设计目标之一是可以把它移植到绝大多数流行的处理器平台上。然而,RISC体系结构对分段的支持很有限。


Linux内核以有限的方式使用分段,它将所有的段的基地址设为0,也就是说线性地址与逻辑地址的偏移相等,由于基地址为0,所以线性地址与逻辑地址一致(注意不要说成相等,是线性地址与逻辑地址的偏移相等),这样Linux就巧妙的绕过了分段。Linux使用的段只有4个,用户代码段,用户数据段,内核代码段,内核数据段。下图中的DPL指定了特权级,当DPL=3时,使用用户态下的代码段和数据段,当DPL=0时,使用内核态下的代码段和数据段。每个段的段描述符占8个字节。


<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

相应的段选择符由宏__USER_CS,__USER_DS,__KERNEL_CS,__KERNEL_DS分别定义。

注意这里的__USER_CS等都是段选择符,不是段描述符。这里其实就是将index<<3+RPL,因为index是段选择符的3~15位。
把其中的宏替换成数值:

计算出index,TI,RPL:

<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

GDT& LDT

最后一个话题就是全局描述符表和局部描述符表。这些段描述表存放在全局描述符和局部描述符表中。全局描述符表GDT是每CPU一个,而LDTINTEL规定每进程一个,但是在Linux中大多数进程共享GDT中的LDT,少数进程除外,比如wine进程就用自己的局部描述符表。所有的gdt都存放在cpu_gdt_table数组中,而所有的gdt的地址和他们的大小存放在cpu_gdt_descr数组中。

<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

4个段描述符在gdt中的表项:

<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

按照上边那张描述符的表可以看出BASE字段都为0x00000000


写了一个helloworld程序,反汇编,在main函数中调用的printf,这里call调用线性地址0x8048318处的代码,访问代码段:

画了一张流程图:


<style type="text/css"><!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --></style>

gdb调试,info reg部分的内容:

可以看到cs为115,00000000 0111 0011,index为14,TI为0,RPL为11。TI为0说明使用的是gdt,RPL为11说明是用态的,index为14,但是想得到相应的段描述符并不是用gdtr中的值(即gdt全局描述符表的起始地址)直接加index,由于一个描述符占8个字节,所以描述符的地址为gdtr中的值+index*8。这样就可以取出描述符中的BASE字段,即段的起始地址,本例子中是用户态的代码段,即0x00000000,加上偏移0x8048318,就可以得到线性地址了。

分享到:
评论

相关推荐

    Linux常见驱动源码分析(kernel hacker修炼之道全集)--李万鹏

    Linux常见驱动源码分析(kernel hacker修炼之道)--李万鹏 李万鹏 IBM Linux Technology Center kernel team 驱动资料清单内容如下: Linux设备模型(中)之上层容器.pdf Linux设备模型(上)之底层模型.pdf Linux...

    常见驱动源码分析(kernel hacker修炼之道)-李万鹏

    这本书是“Linux kernel hacker修炼之道”的一部分,通过深入剖析各种常见的驱动源码,帮助读者提升在Linux系统中的驱动开发能力。 在Linux操作系统中,驱动程序是连接硬件与内核的桥梁,它们负责管理和控制硬件...

    常见驱动源码分析(kernel hacker修炼之道)

    《常见驱动源码分析(kernel hacker修炼之道)》这本书或课程很可能深入探讨了如何理解和编写这些驱动,旨在帮助开发者提升对Linux内核和驱动编程的理解。在这个过程中,我们将会涉及到几个关键的知识点: 1. **Linux...

    linux kernel修炼之道

    如果刚刚对linux的kernel有兴趣,想了解点什么的话,请先看看此书吧,她风趣幽默的介绍了linux的发展趣事,让你开心快乐之余慢慢领会linux的魅力,让你了解学习掌握kernel的方法。其中的很多建议经过我的实践和摸索...

    Linux内核驱动笔记

    内存管理负责分配、回收内存资源,管理虚拟内存和物理内存的映射关系,并实现内存保护机制。 Linux内核支持多种文件系统,例如ext2、fat、isofs等。虚拟文件系统(VFS)是Linux内核中的一个重要概念,它为不同文件...

    Linux PCI驱动牛人论文

    PCI总线之所以能取代旧式ISA总线,主要得益于以下三大优势: - **高性能数据传输**:PCI总线在计算机与外设之间的数据传输能力远超ISA总线。 - **平台独立性**:PCI总线的设计不受特定硬件平台限制,实现真正的平台...

    processhacker-2.39-bin

    ProcessHacker是一款强大的系统信息工具,它提供了进程管理、服务管理、硬件监控、内存查看等多种功能,深受系统...通过下载并使用"processhacker-2.39-bin"压缩包,你将能够亲身体验这些功能并提升你的系统管理技能。

    hacker成长之道

    有关hacker 的文章和资料分享给大家

    进程黑客(Process Hacker)Processhacker-3.0.4132

    Process Hacker是一款针对高级用户的安全分析工具,它可以帮助研究人员检测和解决软件或进程在特定操作系统环境下遇到的问题。除此之外,它还可以检测恶意进程,并告知我们这些恶意进程想要实现的功能。 Process ...

    x64_processhacker_源码

    Process Hacker是一款开源、免费且功能强大的系统信息工具,它允许用户查看并管理正在运行的进程、服务、线程以及内存等系统资源。 【描述】"Process Hacker 1.1 PH1" 提示我们这是Process Hacker的早期版本,版本...

    The-Hacker-Playbook-3-Translation-master.zip

    渗透测试教程资料

    Algorithm-HackerRank-Solutions-In-Scala.zip

    《Scala语言解构HackerRank算法挑战》 在编程领域,算法是不可或缺的一部分,它为计算机程序提供了高效、系统地解决问题的方法。Scala是一种多范式编程语言,融合了面向对象和函数式编程的特点,因其强大的表达能力...

    rails-hackernews-reddit-producthunt-clone, 黑客 news/reddit/social 链接分享网站 用 Rails 构建.zip

    rails-hackernews-reddit-producthunt-clone, 黑客 news/reddit/social 链接分享网站 用 Rails 构建 Rails 上的 Reddit-Hackernews-ProductHunt克隆演示 这是一个 readme.md的Ruby on Rails 应用程序,模仿了 Hacker...

    Hacker 2012.

    Hacker 2012 - Final Transfer Readme =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Thank you for downloading Hacker 2012! Registration ------------------------------------ If you like the game, ...

    processhacker-2.23-setup

    Process Hacker是一款功能丰富的系统程序,比windows自带的任务管理器功能更强大。用户只要借助该程序就可以方便,快捷地查看相关进程的速度,内存,及模块等等,除此,还可以对相关的进程进行管理工作。

    processhacker-2.39-src.rar

    Process Hacker是一款强大的系统进程管理工具,开源,并且还可以显示CPU、GPU、IO、内存等相关使用信息。 官网地址:https://processhacker.sourceforge.io/ git地址:...

    进程浏览器和内存编辑器Process Hacker

    Process Hacker 2是一种开源工具,用于监视系统进程、服务、网络连接等信息,并且还可以进行系统调试和修改。它可以帮助用户更好地了解系统运行情况,识别系统中的问题和优化系统性能。 使用Process Hacker 2可以...

    Resource Hacker - 版本 3.4.0

    Resource Hacker 可以被用来: 1. 查看 Win32 可执行和相关文件的资源 (*.exe, *.dll, *.cpl, *.ocx),在已编译和反编译的格式下都可以。 2. 提取 (保存) 资源到文件 (*.res) 格式,作为二进制,或作为反编过的译...

Global site tag (gtag.js) - Google Analytics