如何确定哪个逻辑核共享同一个物理cpu 逻辑cpu 核数核心

您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
逻辑核动态可重的众核处理器体系结构.pdf 132页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
逻辑核动态可重的众核处理器体系结构
你可能关注的文档:
··········
··········
随着半导体技术的发展,摩尔定律继续有效,单块芯片上集成的处理器核数
将不断增加;同时为追求更高的性能功耗比和性能面积比,众核结构成为芯片设
计的必然选择。众核处理器中丰富的计算资源和高效的片上通信使得面向吞吐率
的应用具有天然的性能优势,但是由于处理器核粒度变小,在单核上执行串行应
用的性能无法保证。为解决这一问题,近年来具有逻辑核构造能力的众核处理器
体系结构研究备受关注,其基本思想是基于多个细粒度处理器核(称为物理核)
构建粗粒度逻辑核,期望利用众核结构丰富的计算资源,将不断增加的处理器核
转化为单线程串行应用的性能提升。目前已有的工作对这种众核结构的通信开销
处理、逻辑核粒度配置灵活性和应用映射方式等方面尚缺乏深入的研究。
本文针对细粒度众核结构上串行程序的有效执行问题,从执行模型、微结构
设计和动态资源控制等几方面展开深入探讨,对于探索逻辑核动态可重构的众核
处理器体系结构具有重要的学术意义和应用价值。本文主要研究内容和成果包括
以下几个方面。
(1)研究了具有逻辑核构造能力的众核处理器重构开销问题,提出逻辑核
动态可重构的众核结构FTPA(Flexible
类数据流驱动执行的指令集体系结构,在不改变串行编程模型前提下,利用数据
流驱动和线程级推测相结合的执行模型,同时开发单线程程序中的指令级并行和
线程级并行。为解决众核处理器逻辑核重构开销过大问题,FTPA将物理核内资
源通过片上路由网络划分为易重构的计算资源和不易重构的共享资源,从而使得
逻辑核粒度能够在两个层面以两种频度进行异步调整,具有高度灵活性。
(2)研究了串行程序采用细粒度线程级推测执行模型时,应用推测执行能
力的实时评估机制。针对串行应用不同执行阶段并行性特征存在的显著差异,利
用时间局部性,为众核结构逻辑核粒度动态重构进行有效指导,本文提出基于“推
测执行阶段”和“推测深度”概念的线程级推测执行能力量化评估方法,并以此
为基础提出利用推测深度的局部历史、全局历史和锦标赛三种推测执行能力评估
器设计,只需要数十位存储资源,就可以有效预测串行程序并行性变化趋势,对
推测深度作出有效估计。
(3)研究了将推测执行能力评估器用于指导FTPA众核结构逻辑核动态重
构的有效性。为有效处理众核结构分布式执行导致的通信开销,以指令窗口和功
能部件为核心的计算资源可以按照平铺式和深度式两种映射方式构建逻辑核,从
而适应具有不同并行性特征的应用。本文将线程级推测执行能力评估器用于指导
FTPA逻辑核动态重构,分别从平铺式映射和深度式映射两方面对性能和资源利
用进行了详细实验评估。结果表明,相对于采用固定粒度逻辑核的FTPA配置,
动态逻辑核重构方式只需一半物理核计算资源就可以有效支持细粒度线程级推
测执行,性能降低不到13%,资源利用率显著提高。
本文的研究工作可以得出如下认识:
(1)逻辑核是众核处理器上加速串行应用的有效手段,但是将细粒度物理
核资源耦合在一起需要高效的结构支持,如本文提出的计算资源和共享资源的分
离设计,平铺式和深度式映射方式等。
(2)在众核处理器上采用细粒度线程级推测执行模型加速串行程序需要在
性能和资源利用率之间进行权衡,合理的逻辑核重构必须建立在对应用执行特征
精确认识的基础上,线程级推测执行能力评估器是一种有效尝试。
本文提出的FTPA众核处理器所采用的计算资源和共享资源分离方法、平铺
式和深度式逻辑核重构以及线程级推测执行能力评估器设计等都可以作为一般
方法论进行推广,应用于其他众核结构中。
关键词:众核处理器物理核逻辑核推测执行能力评估器
ofsemiconductorMoore’SLawiscontinuing,
technology,the
正在加载中,请稍后...个回答我为你开设了这个课程:/// &summary&
/// Provides CPU information
/// &/summary&
public static class Processor
private static IHardwareCore[]
private static int[] logicalC
/// &summary&
/// Hardware core
/// &/summary&
public interface IHardwareCore
/// &summary&
/// Logical core IDs
/// &/summary&
int[] LogicalCores { }
/// &summary&
/// Hardware cores
/// &/summary&
public static IHardwareCore[] HardwareCores
return cores ?? (cores = GetLogicalProcessorInformation()
.Where(x =& x.Relationship == LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore)
.Select(x =& new HardwareCore((UInt64)x.ProcessorMask))
.ToArray&IHardwareCore&());
/// &summary&
/// All logical core IDs
/// &/summary&
public static int[] LogicalCores
return logicalCores ?? (logicalCores = HardwareCores
.SelectMany(x =& x.LogicalCores)
.ToArray());
/// &summary&
/// Current logical core ID
/// &/summary&
public static int CurrentLogicalCore
get { return GetCurrentProcessorNumber(); }
private class HardwareCore : IHardwareCore
public HardwareCore(UInt64 logicalCoresMask)
var logicalCores = new List&int&();
for (var i = 0; i & 64; ++i)
if (((logicalCoresMask && i) & 0x1) == 0)
logicalCores.Add(i);
LogicalCores = logicalCores.ToArray();
public int[] LogicalCores { }
#region Exports
[StructLayout(LayoutKind.Sequential)]
private struct PROCESSORCORE
public byte F
[StructLayout(LayoutKind.Sequential)]
private struct NUMANODE
public uint NodeN
private enum PROCESSOR_CACHE_TYPE
CacheUnified,
CacheInstruction,
CacheData,
CacheTrace
[StructLayout(LayoutKind.Sequential)]
private struct CACHE_DESCRIPTOR
public byte L
public byte A
public ushort LineS
public uint S
public PROCESSOR_CACHE_TYPE T
[StructLayout(LayoutKind.Explicit)]
private struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION
[FieldOffset(0)]
public PROCESSORCORE ProcessorC
[FieldOffset(0)]
public NUMANODE NumaN
[FieldOffset(0)]
public CACHE_DESCRIPTOR C
[FieldOffset(0)]
private UInt64 Reserved1;
[FieldOffset(8)]
private UInt64 Reserved2;
private enum LOGICAL_PROCESSOR_RELATIONSHIP
RelationProcessorCore,
RelationNumaNode,
RelationCache,
RelationProcessorPackage,
RelationGroup,
RelationAll = 0xffff
private struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION
public UIntPtr ProcessorM
public LOGICAL_PROCESSOR_RELATIONSHIP R
public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorI
[DllImport(@&kernel32.dll&, SetLastError = true)]
private static extern bool GetLogicalProcessorInformation(
IntPtr Buffer,
ref uint ReturnLength
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private static SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] GetLogicalProcessorInformation()
uint ReturnLength = 0;
GetLogicalProcessorInformation(IntPtr.Zero, ref ReturnLength);
if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength);
if (GetLogicalProcessorInformation(Ptr, ref ReturnLength))
int size = Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
int len = (int)ReturnLength /
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] Buffer = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[len];
IntPtr Item = P
for (int i = 0; i & i++)
Buffer[i] = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)Marshal.PtrToStructure(Item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
Marshal.FreeHGlobal(Ptr);
[DllImport(@&kernel32.dll&, SetLastError = true)]
private static extern int GetCurrentProcessorNumber();
#endregion
}用法示例:for (var i = 0; i & Processor.HardwareCores.L ++i)
Console.WriteLine(&Hardware Core {0} has logical cores {1}&, i,
string.Join(&, &, Processor.HardwareCores[i].LogicalCores));
Console.WriteLine(&All logical cores: & + string.Join(&, &, Processor.LogicalCores));
Console.WriteLine(&Current Logical Core is & + Processor.CurrentLogicalCore);示例输出英特尔核心i5:Hardware Core 0 has logical cores 0, 1
Hardware Core 1 has logical cores 2, 3
All logical cores: 0, 1, 2, 3
Current Logical Core is 2  【摘 要】高中物理很重要的一个内容就是对概念的学习,而核心概念的学习更是概念学习的重中之重,高中物理的核心概念有11个" />
免费阅读期刊
论文发表、论文指导
周一至周五
9:00&22:00
高中物理核心概念的学习方法研究
  【摘 要】高中物理很重要的一个内容就是对概念的学习,而核心概念的学习更是概念学习的重中之重,高中物理的核心概念有11个,本文先对核心概念学习的重要性做一评估,然后具体地结合这11个概念进行学习方法的探讨。通过条分缕析的探讨,可以帮助学生更好地学好高中物理概念,同时对教师的教学水平也是一个提高。 中国论文网 http://www.xzbu.com/9/view-5785742.htm  【关键词】高中物理 核心概念 学习方法 研究   【中图分类号】G632 【文献标识码】A 【文章编号】(7-01   一 高中物理核心概念学习的重要性   1.能完善高中生的知识结构   高中物理的核心概念是高中物理知识的高度概括与抽象总结。在初中的物理知识中,往往是对实验现象的认识和对知识的表象认识。在进入高中物理的学习阶段后,学生需要更多地摆脱表象认识,试着从原理的角度来认识和解决问题。对高中物理核心概念的学习,能丰富和完善高中生的知识结构,提高自己认知和解决问题的能力。   2.能加强各个知识点的联系,强化学习效果   我们知道,高中物理有力学、电学等核心知识点。在传统的学习中,不注重对核心概念的学习,往往造成学生各个知识点的学习是割裂的,没有一定的内在逻辑。通过对核心概念的学习,学生能把一个知识点的学习体验来迁移到另一个知识点上,往往能起到事半功倍的效果,能使学生在已有的理解的基础上支持后来的学习。   二 高中物理核心概念学习方法探讨   1.核心概念的简介与梳理   “运动”是力学的重要概念。在这一节中,有两个重要的知识点,首先是位移这一概念和初中时学的不是同一个概念,这是第一个要注意的点。第二个重要的点是加速度概念的引入。“机械能守恒”主要在于介绍动能、势能及其之间的转化。通过机械能守恒,我们可以引入到“动量守恒”。这也就是文中提到过的,让学生通过对核心概念的学习,可以把各个知识点联系起来,因为这些知识点本身就不是割裂的,而是有着自身的内在逻辑关系。   在电学的一系列概念中,有四个是比较核心的概念,分别是静电场、恒定电流、电磁波、磁场,因为这四个概念是贯穿在其他概念中的,如果能深入理解这四个核心概念,才能为其他概念的学习打下坚实的基础。在“分子动理论”这一章节中,我们可以发现,不管是“热力学定律”还是物体的三大形态之间的转化,都与“分子动理论”有着内在联系,因而我们把“分子动理论”作为这一章节的核心概念来学习,通过这一概念的深入理解,可以更好地理解为什么物体的形态在一定条件下可以转化等神奇的自然现象。在光学的学习中,我们把“几何光学初步”和“物理光学初步”作为两个核心概念来学习。因为不管是光的折射,还是光的偏振和光的色散都和这两个概念有关。   其他的核心概念还有原子的结构、原子的变化、波粒二象性和相对论这几个概念。这些核心在它们所属的章节中,都是核心概念,此处不再赘述。   2.核心概述的学习方法探讨   在总结的11个核心概念中,在五大领域的分布如下:力学2个、电学2个、热学2个、光学2个、近代物理3个。接下来,我们主要谈谈这些核心概念的学习问题。   第一,以“能量守恒”的学习为例。在“能量守恒”这一概念的学习中,学生要注意知识的前后衔接。我们知道,在小学和初中,我们对“能量”这一概念有所认识。小学生对能量的理解是肤浅的,如电能发光、热能传递,这种表象化的理解是我们在小学阶段对“能量”的主要理解。在初中阶段,我们对“能量”的理解有所深化,但是在初中阶段并没有引入“分子动能”这一概念的理解,所以也不能真正理解能量。   进入高中阶段后,对能量的理解,要更多的和能量的定量、守恒这些性质联系起来,自觉地对能量守恒这一概念进行前后衔接的深入理解。此外,教师可以介绍原子能与其他能量的转化、核能产生的具体机制及其转化,电势能与其他能量的转化、定量掌握各种机械能之间的转化和机械能守恒等能量守恒的形式,帮助学生对“能量守恒”这一概念深入理解。   第二,教师对学生概念性的引导。通过上文我们以“能量守恒”这一核心概念的学习为例,我们发现,在核心概念的学习中,教师起着很大的作用,这种作用体现在概念性的引导方面,体现在知识扩展的引入方面。老师们不用担心过多概念的引入会加重学生的学习负担。因为知识有着系统性的特点,单一概念的学习反而会引起学习效果不佳,而旁及概念的引入,多概念会更好地帮助学生学习、理解高中物理中的核心概念。   第三,学生自觉地衔接前后对概念的理解。通过我们对“能量守恒”这一核心概念具体学习方法的介绍,我们发现,学生自觉地衔接小学和初中对某一概念的理解,能不断地丰富自己的知识体系,强化对现阶段的物理知识的理解。   三 结束语   通过对高中物理核心概念的界定,可以发现,这些核心概念贯彻了整个高中物理的学习过程。在对这些核心概念的学习方面,一方面老师要做到概念性的引导和拓展,同时,学生更要在对核心概念的学习中发挥自己的主体作用。常言道:教学相长,通过核心概念的教学,教师本身也在不断地丰富自己对高中物理核心概念的理解。   参考文献   [1]范增.我国高中物理核心概念及其学习进阶研究[D].西南大学,2013   [2]张军朋、段世英.国外学生对能量概念理解的研究概述[J].中学物理教学参考,2004(1)   [3]张运科.中学生持有电流消耗模型之成因及其转变的实证研究[D].广西师范大学,2011   〔责任编辑:范可〕
转载请注明来源。原文地址:
【xzbu】郑重声明:本网站资源、信息来源于网络,完全免费共享,仅供学习和研究使用,版权和著作权归原作者所有,如有不愿意被转载的情况,请通知我们删除已转载的信息。
xzbu发布此信息目的在于传播更多信息,与本网站立场无关。xzbu不保证该信息(包括但不限于文字、数据及图表)准确性、真实性、完整性等。[原创]利用内核知识,自己实现ReadProcessMemory
前言转眼来到科锐学习已经超过一年的时间了,眼看三阶段已经进入尾声,内核的学习也快要结束,记录一下笔记和心得,也给刚接触的朋友做一个参考。当然,学习新知识最好的办法就是带着目的来学习,所以在文章后半部分,介绍如何自己实现了Windows的一个API:ReadProcessMemory,为什么要选这个API呢?首先在软件保护上,任何开发者都不会希望别人可以随意查看自己的内存内容,于是多数人会选择在这个函数上挂钩,监视并保护内存,那么我们可以绕过他的保护,用自己的函数来查看进程内存。
本篇文章主要涉及两个部分:
介绍内核基础知识
自己实现ReadProcessMemory
环境介绍:真机64位Windows10,虚拟机:32位XP_sp3
学习内核的本质其实是学习操作系统的原理,而学习的过程应该是从CPU架构出发,操作系统作为使用CPU提供功能的例子。第一部分:内核基础知识内核可以分成两类:
宏内核:追求性能,大部分系统代码放在0环,代表:Linux
微内核:追求维护性,大部分系统代码在3环,代表:Minix(Linux作者老师的作品),其中著名的设计:动态链接库,在Windows中也使用
Windows算是微内核和宏内核特点都具有的操作系统。
80x86处理器的工作模式:8086处理器有三种工作模式,分别是:实模式,保护模式,虚拟86模式,其中关系为:
16位汇编中 iret可以进入保护模式。
分段式内存管理如何保证操作内存的动作是否合法?
GDT、LDT操作系统通电后进入实模式,做了一系列初始化的动作后进入到保护模式,在保护模式中,CPU执行所有和内存有关的操作都会通过查表来确定操作是否合法,这个表就是GDT和LDT表,表的格式由CPU厂商决定,所以为了能兼容多款CPU,操作系统代码里多用条件宏来实现。
地址的转换
逻辑地址:在程序调试中见到的地址,实际上是:段+偏移的形式
线性地址:逻辑地址转物理地址的中间层,逻辑地址是段中的偏移地址然后加上基地址就是线性地址。
物理地址:物理内存条上的真实地址
逻辑地址如何转换到物理地址?首先通过逻辑地址的偏移查第一次表得到线性地址,再查第二次表得到物理地址。为什么要查第二次表呢?因为第二张表实际上是为了实现虚拟内存,那么就是说这段内存可能是在磁盘上的,访问的时候会先查表,然后从磁盘上调到内存中,有些情况下(关闭了虚拟内存)查第一次表的结果等价于物理地址。
为什么要叫线性地址?从逻辑地址转换到线性地址,是一块平坦且连续的地址,实际上对应到物理地址上,并不是连续的。
如何计算线性地址的范围?例如:
设段A的基地址等于H,段界限等于5678H,并且段界限以字节为单位(G=0),那么段A对应线性地址空间中从0179BDH的区域。
如果段界限以4K字节为单位 (G=1),那么段A对应线性地址空间中从68B344H(=78000H+0FFFH) 的区域。
如何从逻辑地址
===查表===&&
线性地址?这个表也叫做分段表,结构如下图:
这种奇葩的做法来源于为了兼容286的历史遗留问题。
描述符用于表示上述定义段的三个参数的数据结构称为描述符。每个描述符长8个字节。在保护方式下,每一个段都有一个相应的描述符来描述。
存储段描述符存储段是存放可由程序直接进行访问的代码和数据的段。存储段描述符描述存储段,所以存储段描述符也被称为代码和数据段描述符。
&描述符是一个8个字节的结构,具体结构如下:
Limit 0:15项和Limit 16:19项一起构成20位的段界限。20位的段界限最大值为0xFFFFF,单位是字节或者分页(有Flags项Gr位来确定)。在分页机状态下最大可以表达4G的内存空间。
Base0:23项和Base24:31一起构成32位的段基址,是线性还是物理地址也取绝于分页机制是否开启。
整个的解析结构如下图:
Access Byte
Pr:存在位,对于一个有效的内存分段此值必定为1。
Privl(2bit):优先级位,取值从0-3,对应Ring0-Ring3级别。
Ex:可执行位,为1时表示此描述符对应是代码段,为0时为数据段。
对于数据段,表于数据段的增长方向,0表示向上。1表示向下,也就是偏移大于段基址。
对于代码段,表示是否遵循一致原则。当此位为1时,也就是遵循一致原则,不同优先级代码跳转时,优先级同目标代码所在段一致。为0时,刚跳转时优先级不变。
R/W:读写位
对于数据段,为1时表示可写,为0时表示不可写。数据段总是可读。
对于代码段,为1时表示可读,为0时表示不可读。代码段总是不可写。
Ac:保留位,设置为0,当被访问过时系统将其改写为1。
Gr:表示段界限的单位也叫做粒度,为1时表示单位为4KB(一个页面),为0时表示单位为1字节。
Sz:区分是16位保护模式,还是32位保护模式。可以同时有两种类型描述符在同一个GDT中。
全局和局部描述符表
每个任务的局部描述符表LDT含有该任务自己的代码段、数据段和堆栈段的描述符,也包含该任务所使用的一些门描述符,如任务门和调用门描述符等。随着任务的切换,系统当前的局部描述符表LDT也随之切换。
全局描述符表GDT含有每一个任务都可能或可以访问的段的描述符,通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述符,也包含多种特殊数据段描述符,如各个用于描述任务LDT的特殊数据段等。在任务切换时,并不切换GDT。
通过LDT可以使各个任务私有的各个段与其它任务相隔离,从而达到受保护的目的。通过GDT可以使各任务都需要使用的段能够被共享。
&GDT存储在GDTR寄存器, 通过汇编指令LGDT载入。它的操作码是一个结构的地址,这个结构描述GDT的大小和地址。共6个字节,如下:
Size项(2个字节)是GDT的字节数减1(这也意味着GDT大小不可能为0)。2个字节对应最大值是65535,也就是说一个GDT最大也就是65536字节(8192个内存分段)。
Offset项(4个字节)指向GDT的线性地址(未开启分页机制则是物理地址)。
LDT存在LDTR寄存器中,存有局部进程的描述符表,LDTR中的内容根据线程的切换不停切换,表中的内容由操作系统来修改,若我们拿到0环权限,自己修改LDTR,改到目标进程,那么修改自己的内存就相当于修改了目标进程的内存,这是内核修改的一个经典招式。
通过段选择子确定逻辑地址到物理地址的转化(未开启分页机制)段选择子在保护方式下,虚拟地址空间(相当于逻辑地址空间)中存储单元的地址由段选择子和段内偏移两部分组成。段选择子长16位,在32位程序下,CPU的段寄存器中保存的就是选择子,其格式如下表所示:
段选择子的高13位是描述符索引(Index):所谓描述符索引是指描述符在描述符表中的序号。
段选择子的第2位是引用描述符表指示位,标记为TI(Table Indicator),TI=0指示从全局描述符表GDT中读取描述符;TI=1指示从局部描述符表LDT中读取描述符。 (windows不使用这种CPU的做法,而Linux使用)
RPL:特权级描述符,CPU比较这一项个描述符的特权级判断访问操作是否能进行下去
具体通过逻辑地址查找线性地址的例子:现有逻辑地址:23:13ac34b,假如段寄存器中的的选择子Index为:0,RPL:11,先比对,是三环程序,继续操作,去LDT表中的第4项拿到段首地址,加上偏移13ac34b,得到线性地址。
值得一提的是Windows中并没有使用LDT,而Linux是使用了LDT的,但是有意思的是在阅读Windows源码时发现微软也留下了LDT的接口,难道微软想什么时候顺便兼容一下Linux?
分页管理80386开始支持存储器分页管理机制。分页机制是存储器管理机制的第二部分。上述的段管理机制实现虚拟地址(由段和偏移构成的逻辑地址)到线性地址的转换,分页管理机制实现线性地址到物理地址的转换。
线性地址到物理地址的转换线性地址到物理地址的转换方式受很多变量的影响,我们先以一个其中最具代表性的方式来讲解基本概念和转换流程,再来总结所有的转换方式。
&流程如图所示采用了二级表的结构:
页目录表(PDE)一级表称为页目录表(Page Directory Entry),共有1024(1k)个表项,每个表项的大小是4bit,总大小为4k,表项内容包括了页表的指针和指向页表的属性。
页表(PTE)二级表称为页表(Page Table Entry),每张页表里有1024(1k)个表项,每个表项的大小是4bit,总大小为4k,最多有1024(1k)张页表,最大占用空间为4M,而操作系统一般是动态申请页表,大小大概在1M左右。表项内容包括了物理地址的指针和属性。
CR3控制寄存器CR3的高20位存放了指向页目录表的指针(这里存的是物理地址,如果这里存虚拟地址就会产生悖论),每个进程都会有一张PDE,切换进程其实就是CPU在切换CR3的值,这一点非常重要,是我们自己实现ReadProcessMemory的基础!
表项PDE和PTE的表项结构基本相似,略有差别,如下图所示:
页目录表表项:
结构基本类似,高20位存指向目标首地址,低12位表示指向目标的属性
P:Present,存在标志,该标志标明当前表项所指向的页或页表是否存在于内存中。当标志位置位表示该页在内存中,当标志位清零表示该页不在内存中,若CPU试图访问则会产生一个缺页异常,值得一提的是CPU并不会主动操作该标志位,而是让操作系统来维护。
R/W:Read or Write,读写标志位,当标志位置位,所指页表或页是可读可写的,清零表示所指页表或页是只读的。
U/S:User or Surpervisor,用户权限标志,置位时表示普通用户权限也就是我们常说的3环权限,清零则表示超级用户权限也就是0环权限。
PWT:Page Write Through,页直写标记,控制页或页表的直写或回写缓存策略。
PCD:Page Cache Disabled,页层次的缓存禁用,控制页或页表的的缓存,置位时缓存被禁止,清零时表示可以缓存。
A:Accessed,访问标志,指明这个页或页表是否曾经被访问过,当指向的页或页表第一次载入内存,会清零标志位,当页或页表第一被访问,改标志位置位
D :Dirty,脏位(在PDE的表项中,该位是0,不使用此标志位),指明该页是否曾经被写入过,,当指向的页第一次载入内存,会清零标志位,当页第一次写操作完成,改标志位置位
PAT:Page Table Attribute Index(PTE表项中的第7位)页属性索引。
PS :Page Size(PDE表项中的第7位),该位指明指向的页表尺寸,当改标志清零,页尺寸为4k。当改标志被置位,页的尺寸为32位寻址的4M(物理地址拓展启用,页尺寸为2M)
G:Global,全局标志。
Avl:保留位。
32位线性地址结构:
线性地址的最高10位(即位22至位31)作为页目录表的索引
线性地址的中间10位(即位12至位21)作为所指定的页目录表中的页表项的索引
线性地址的低12位作为32位物理地址的低12位。
转换实例:
如何搭建双机调试环境,请自行谷歌
&我们以GDT地址作为例子:寄存器环境:
&gdt内容:
&dd :查看虚拟内存地址
&现在我们有线性地址:0x,CR3:39000
拆分线性地址:
PDE Index:0x200
PTE Index :0x3f
Offset :0x0
页目录表首地址为CR3的高20位,找到对应页目录表项:
!dd:查看物理内存地址, 0x200 * 4是因为表项是4个字节
表项 0x的前20位指向页表的首地址,也就是0x,页表的Index为0x3f,于是:
表项0x的前20位指向物理地址页,也就是0x,加上Offset,最后得到物理地址:0x。
检验:和虚拟地址对应的内容是相同的,说明虚拟地址:0x映射到物理地址:0x
所有转换方式(查表方式):以上我们所阐述的线性地址转物理地址的方法适用于没有物理地址拓展,且页表大小为4k的情况。
如何决定适用哪种查表方式?查表方式根据页表大小来决定,而页表大小根据以下标志决定:
PG:分页标志,CR0的31位
PSE : 页尺寸拓展标志,CR4的第4位
PAE : 物理地址拓展标志,CR4的第5位
PS :页表尺寸,PDE表项中的第7位
未开启PAE,页表大小4k
以下图片均来自Intel手册,详细解释请参考手册
未开启PAE,页表大小4M
&当符合页表大小是4M的情况下,只需要查一次PDE表再加上偏移就能得出物理地址。
开启PAE分页机制的36位物理寻址开启PAE时,寻址的方式有所不同,CR3里保存的不再是PDE的首地址,而是一个保存了PDE指针的表的首地址,这张表我们称作页目录指针表(PDPT),对于线性地址的拆分也有所不同,高两位作为了PDPT的索引。
开启PAE,页表大小4K
&当开启PAE且页表大小是4k的情况,需要查三次表,线性地址的21-29位作为PDE表的索引,12-20位作为PTE表的索引
开启PAE,页表大小2M
第二部分:ReadProcessMemory的实现说了这么多关于表的格式和查表的方法,在实践中我们该如何利用呢?一个用处是我们经常需要把虚拟地址转换成物理地址,明白其转换原理利于分析问题,另外上面说了,每个进程都会有一套自己的分页机制,切换进程实际上是切换CR3中的内容,那么如何实现我们自己的ReadProcessMemory呢?
&问题变成了以下4步:
拿到指定进程保存在CR3中的内容
切换当前的CR3
读取指定内存的内容
第一步,如何拿到指定进程保存在CR3中的内容?我们知道在3环程序里,fs[0]保存的是线程环境块TEB,在0环,保存的则是处理器控制区(_KPCR),部分内核数据结构如下图:
&从_EPROCESS中的进程链表我们可以遍历所有进程,当匹配到目标进程时,拿出目标进程DirectoryTableBase中保存的地址。
NTSTATUS GetProcessDirBase(IN DWORD dwPID, OUT PDWORD pDirBase)
PEPROCESS P
PEPROCESS CurP
*pszImageN
DWORD dwCurPID;
mov eax, fs:[124h]
//Current EPROCESS
mov eax, [eax + 44h]
mov Process, eax
CurProcess = P
//traversing
pszImageName = (char*)CurProcess + 0x174;
dwCurPID = (*(DWORD*)((char*)CurProcess + 0x084));
if (dwCurPID == dwPID)
*pDirBase = (*(DWORD*)((char*)CurProcess + 0x018));
return STATUS_SUCCESS;
CurProcess = (*(DWORD*)((char*)CurProcess + 0x088)) - 0x88;
} while (CurProcess != Process);
__except (EXCEPTION_EXECUTE_HANDLER)
dprintf("[MyReadProcessMemory] GetProcessDirBase __except \r\n");
return STATUS_INVALID_DEVICE_REQUEST;
第二步,切换当前的CR3切换CR3的值之前,我们需要屏蔽调当前CPU核心的中断,以防线程切换,如果是多核的CPU,每个核心都需要屏蔽掉中断。同时,为了预防内存属性不可写,暂时改掉CR0中表示所有内存属性的标志,让所有内存暂时都可写。
//Shielding interrupt
//close memory protect
mov eax, cr0
and eax, not 10000h
mov cr0, eax
mov eax, cr3
mov dwOldDirBase, eax
//swap CR3
mov eax, dwDirBase
mov cr3, eax
第三步,读取指定内存的内容申请一段空间,暂存一下读取的数据,记得要检查目标内存地址是否有效
//Alloc ring0 Buff
char* szRing0Buf = (char*)MmAllocateNonCachedMemory(dwBufSize);
//check address invalid
if (MmIsAddressValid(dwTargetAdddress))
RtlCopyMemory(szRing0Buf, dwTargetAdddress, dwBufSize);
bIsRead = TRUE;
第四步,还原CR3恢复内存属性,恢复中断
mov eax, dwOldDirBase
mov cr3, eax
memory protect
mov eax, cr0
eax, 10000h
mov cr0, eax
//Restore interrupt
总结内核的学习也开始进入尾声,温故而知新,整理知识本身也是一种学习的过程。衷心感谢一年多以来钱老师,张老师,姚老师,戚老师,王老师,唐老师的指导。要毕业了,帮科锐宣传下,科锐30期正在招生中
上传的附件:
(304.37kb,31次下载)
支付方式:
最新回复 (24)
干货很多,希望以后多来分享!
,向大佬学习,以后大佬的笔记就是我的工具书?
很详细,收走了
看了帖子感觉学到了很多遗漏的东西。对自己的知识又有了补充。
我的方案是改pte& map远程进程的内存到本地进程。想干啥就干啥
我的方案是改pte map远程进程的内存到本地进程。想干啥就干啥
想了下,确实是个好方法
难道没有办法防?
难道没有办法防?
有,硬件虚拟化,直接保护物理地址,不过处理很复杂就是了顺便这篇文章没有涉及到一点64位内存管理的东西,全程在讲32位,放到2004年大家都在用xp的年代或许不错。但是今天已经是2018年了,至少也该讲讲64位的东西了吧
HOOK这个RtlCopyMemory函数也是可以防吧
最看到利用VT可以突破任何& 驱动防护。。
最看到利用VT可以突破任何 驱动防护。。
本来就是矛和盾的故事,在同样的竞争下没有谁一定会更强一点,一般来说都是哪边花的精力/钱多哪边就更强
@hzqst& & 随着内核的深入学习,发现目前主流的杀软也太弱& 了& 。。测试了一下。通过PID& 就kill& TX管家。大公司的安全软件都那样。小公司怎么生存。任人鱼肉了& MyKillProcess(HANDLE& Pid){ & & & &HANDLE& hP & & & &NTSTATUS& ret=& MyOpenProcess(Pid,&hProcess,1); & & & &MyTerminateProcess(hProcess); & & & &return&}
随着内核的深入学习,发现目前主流的杀软也太弱 了 。。测试了一下。通过PID 就kill TX管家。大公司的安全软件都那样。小公司怎么生存。任人鱼肉了
MyKillProcess( ...
1、你kill的是GUI进程,主防进程并么有kill掉2、如果你kill的是主防进程,那么你一定加载自己的驱动了。你加载驱动的时候大数字拦截并询问了吗,你大概是点了允许加载驱动吧。
1、你kill的是GUI进程,主防进程并么有kill掉
2、如果你kill的是主防进程,那么你一定加载自己的驱动了。你加载驱动的时候大数字拦截并询问了吗,你大概是点了允许加载驱动吧。
Bypass& Zhudongfangyu& x64& 可没那么好搞~
”屏蔽调当前CPU核心的中断,以防线程切换,如果是多核的CPU,每个核心都需要屏蔽掉中断“我只有一个问题,假设待读的内存页当前处于被交换状态你该如何处理,我只粗略看了一下你的4个小标题。如果是我 我大概会这样做,先挂靠目标进程,然后映射当前进程空间的待读内存到内核然后锁一下(如果嫌麻烦就直接拷贝一份到内核空间),再切回原进程之后去读那个映射/拷贝,最后回收一下资源。挂靠目标进程是个比较大的过程,估计是做了 插apc,修改当前线程所属,陷入等待 唤醒之类的一系列玩意组成的(具体我没看,猜测是这个过程),切CR3 也只是&KiSwapProcess 里面的小小一环,暴力的代价很大(以前测过,最少有一半的目标进程内存是读不到的),为了那一点可有可无的隐蔽性,老实说很亏。如果说仅仅是为了读带保护属性的内存也有其它更好的解决思路。
被FadeTrack编辑
mark一下,up主写的还是很辛苦的& & 鼓励& 鼓励
都是一些老方法了,现在的新系统都不行了。加上win10的的VBS功能,这些东西都没什么用武之地了。
去看看TP大保护的DXF你就晓得你这样根本就读不到内存因为页面已经给你& 替换了& 哈哈.
1.请先关注公众号。
2.点击菜单"更多"。
3.选择获取下载码。

我要回帖

更多关于 逻辑核 的文章

 

随机推荐