MDL(内存描述符表) 详解

合集下载

C语言中内存四区的详解

C语言中内存四区的详解

C语言中内存四区的详解C语言编程2022-05-10 14:00来自:今日头条,作者:抖点料er链接:https:///article/7046019680989037069/1、内存四区1.1数据类型本质分析1.1.1数据类型的概念•“类型”是对数据的抽象•类型相同的数据有相同的表示形式、存储格式以及相关的操作•程序中使用的所有数据都必定属于某一种数据类型1.1.2数据类型的本质•数据类型可理解为创建变量的模具:是固定内存大小的别名。

•数据类型的作用:编译器预算对象(变量)分配的内存空间大小。

•注意:数据类型只是模具,编译器并没有分酤空间,只有根据类型(模具)创建变量(实物),编译器才会分配空间。

1.2变量的本质分析1.2.1变量的概念概念:既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量。

变量定义形式:类型标识符,标识符,…,标识符;1.2.2变量的本质1、程序通过变量来申请和命名内存空间int a = 0。

2、通过变量名访问内存空间。

1.3程序的内存四区模型流程说明1、操作系统把物理硬盘代码load到内存2、操作系统把c代码分成四个区栈区( stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放程序结束时可能由操作系统回收全局区(静态区)(statIc):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,该区域在程序结束后由操作系统释放常量区:字符串常量和其他常量的存储位置,程序结束后由操作系统释放。

程序代码区:存放函数体的二进制代码。

3、操作系统找到main函数入口执行1.4函数调用模型1.5函数调用变量传递分析(1)(2)(3)(4)(5)1.5栈的生长方向和内存存放方向相关代码:02_数据类型本质.c#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>int main(){int a;//告诉编译器,分配4个字节int b[10];//告诉编译器,分配4*10个字节/*类型本质:固定内存块大小别名可以通过sizeof()测试*/printf("sizeof(a)=%d,sizeof(b)=%d\n", sizeof(a), sizeof(b));//打印地址//数组名称,数组首元素地址,数组首地址printf("b:%d,&b:%d\n",b,&b);//地址相同//b,&b数组类型不同//b,数组首地址元素一个元素4字节,+1 地址+4//&b,整个数组首地址一个数组4*10=40字节, +1 地址+40 printf("b+1:%d,&b+1:%d\n", b + 1, &b + 1);//不同//指针类型长度,32位机器32位系统下长度是 4字节// 64 64 8char********* p = NULL;int* q = NULL;printf("%d,%d\n", sizeof(p), sizeof(q));//4 , 4return0;}03_给类型起别名.c#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>typedef unsigned int u32;//typedef 和结构体结合使用struct Mystruct{int a;int b;};typedef struct Mystruct2{int a;int b;}TMP;/*void 无类型1.函数参数为空,定义函数时用void修饰 int fun(void)2.函数没有返回值:使用void void fun (void)3.不能定义void类型的普通变量:void a;//err 无法确定是什么类型4.可以定义 void* 变量 void* p;//ok 32位系统下永远是4字节5.数据类型本质:固定内存块大小别名6.void *p万能指针,函数返回值,函数参数*/int main(){u32 t;//unsigned int//定义结构体变量,一定要加上struct 关键字struct Mystruct m1;//Mystruct m2;//errTMP m3;//typedef配合结构体使用struct Mystruct2m4;printf("\n");return0;}04_变量的赋值.c#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>int main(){//变量本质:一段连续内存空间别名int a;int* p;//直接赋值a = 10;printf("a=%d\n", a);//间接赋值printf("&a:%d\n", &a);p = &a;printf("p=%d\n", p);*p = 22;printf("*p=%d,a=%d\n", *p, a);return0;}05_全局区分析.c#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>int main(){//变量本质:一段连续内存空间别名int a;int* p;//直接赋值a = 10;printf("a=%d\n", a);//间接赋值printf("&a:%d\n", &a);p = &a;printf("p=%d\n", p);*p = 22;printf("*p=%d,a=%d\n", *p, a);return0;}06_堆栈区分析.c#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>char* get_str(){char str[] = "abcdef";//内容分配在栈区,函数运行完毕后内存释放printf("%s\n", str);return str;}char* get_str2(){char* temp = (char*)malloc(100);if (temp == NULL){return NULL;}strcpy(temp, "abcdefg");return temp;}int main(){char buf[128] = { 0 };//strcpy(buf,get_str());//printf("buf = %s\n", buf);//乱码,不确定内容char* p = NULL;p = get_str2();if (p != NULL){printf("p=%s\n", p);free(p);p = NULL;}return0;}07_静态局部变量.c#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>int* getA(){static int a = 10;//在静态区,静态区在全局区return &a;}int main(){int* p = getA();*p = 5;printf("%d\n",);return0;}08_栈的生长方向.c#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>int* getA(){static int a = 10;//在静态区,静态区在全局区return &a;}int main(){int* p = getA();*p = 5;printf("%d\n",);return0;}版权申明:内容来源网络,版权归原创者所有。

MDL(内存描述符表)详解

MDL(内存描述符表)详解

MDL(内存描述符表)详解MDL(内存描述符表)详解分类:初学驱动2013-01-25 18:07 308人阅读评论(0) 收藏举报mdl以下的虚拟内存可以理解成逻辑内存,因为我觉得只有这样才能讲通下面所有的东西。

以下的“未分页”指没有为页进行编码。

以下为MDL结构体(我很郁闷,我在MSDN上没有找到这个结构体)typedef struct _MDL {struct _MDL *Next; //下一个MDLCSHORT Size; //大小CSHORT MdlFlags; //标志,保护属性等struct _EPROCESS *Process;//PVOID MappedSystemVa;PVOID StartVa;ULONG ByteCount;ULONG ByteOffset;} MDL, *PMDL;如何使用MDL:一个连续的虚拟内存地址范围可能是由多个分布(spread over)在不相邻的物理页所组成的。

系统使用MDL(内存描述符表)结构体来表明虚拟内存缓冲区的物理页面布局。

我们应该避免直接访问MDL。

我们可以使用MS-Windows提供的宏,他们提供了对这个结构体基本的访问。

·MmGetMdlVirtualAddress 获取缓冲区的虚拟内存地址·MmGetMdlByteCount 获取缓冲区的大小(字节数)·MmGetMdlByteOffset 获取缓冲区开端的物理页的大小(字节数)·MmGetMdlPfnArray 获取记录物理页码的一个数组指针。

我们可以用IoAllocateMdl函数来分配一个MDL。

如果要取消分配,可是使用IoFreeMdl 函数。

或者,可以使用MmInitializeMdl来把一个之前定义的缓冲区定制成一个MDL。

但是以上两种方式都不能初始化物理页码数组。

对于在未分页池中分配的缓冲区,可以用MmBuidlMdlForNonpagedPool函数来初始化页码数组。

3. MicroStation_MDL

3. MicroStation_MDL
② 除仍然可以用原来的.R资源建立界面外更可以用MFC对话框; ③ 对于复杂的计算量大的程序,在性能上会有较大的提升;
④ 可以利用VS提供的直观而强大的调试功能对程序进行调试。
………….
6 |
© 2009 Bentley Systems, Incorporated
7 |
启动MicroStation Developer Shell,切换到项目所在目录,键
入bmake 进行编译链接生成.ma和.dll MicroStation Developer Shell使用的是 …\MicroStation\mdl\bin\mstndevvars.bat 启动MicroStation,键入MDL LOAD project1装载应用, 然后键入project1 RUN MFCTEST能出现右图所示对话框。
© 2009 Bentley Systems, Incorporated

• •
mdlModelRef_xxx / mdlDgnFileObj_xxx 模型及文件操作类函数
mdlRaster_xxx / mdlRefFile_xxx 等等…… 光栅参考和矢量参考类函数
18 |

• •
mdlTextStyle_xxx/mdlDimStyle_xxx/mdlLineStyle_xxx/mdlMlineStyle_xx x 各种样式的操作函数
mdlVec_xxx / mdlRMatrix_xxx / mdlTMatrix_xxx 几何运算函数 mdlKISolid_xxx / mdlBspline_xxx / mdlMesh_xxx / mdlPop_xxx 三维函数
© 2009 Bentley Systems, Incorporated

(转)MDL及MDL宏MDL函数

(转)MDL及MDL宏MDL函数

(转)MDL及MDL宏MDL函数⼀. MDL是什么 在MSDN中有这样的定义 内存描述符列表 (MDL) 是⼀个系统定义的结构,通过⼀系列物理地址描述缓冲区。

执⾏直接 I/O 的驱动程序从 I/O 管理器接收⼀个 MDL 的指针,并通过 MDL 读写数据。

⼀些驱动程序在执⾏直接 I/O 来满⾜设备 I/O 控制请求时也使⽤ MDL。

因此通俗的解释⼀下,MDL仅仅运⽤于内核中,在应⽤层并不会涉及这个结构,由于内核中的驱动有跟应⽤层程序通信的需要,因此可能会接收到来⾃进程空间的虚拟地址,⽽在windows的分页机制下,进程空间中的任何⼀个虚拟地址所属的页⾯都有可能被内存管理器从RAW置换到页⽂件中,或者,进程被释放或是取消地址的映射。

这些都会导致严重的错误发⽣。

因此内核创建⼀个MDL,并将其与来⾃进程空间的虚拟地址相关联,当需要对这些虚拟地址进⾏读写的时候调⽤相关的内核函数,锁定这些虚拟地址对应的物理页⾯和逻辑页⾯,防⽌物理页⾯被置换,逻辑页⾯被修改或者释放。

另外⼀种情况下⼀个驱动程序在执⾏纯内核任务中也可以使⽤MDL,特别的仅仅调⽤⾮分页内存的话,这些页⾯是不会置换到页⽂件中的,因此不需要考虑锁定页⾯的问题。

⼆. MDL的内容 先看看wdm.h中MDL的定义:typedef __struct_bcount(Size) struct _MDL{struct _MDL *Next;CSHORT Size;CSHORT MdlFlags;struct _EPROCESS *Process;PVOID MappedSystemVa;PVOID StartVa;ULONG ByteCount;ULONG ByteOffset;} MDL, *PMDL; 先⼤概说明⼀下爱各个字段: Next:MDL可以连接成⼀个单链表,因此可以将分散的虚拟机地址串接起来。

Size:⼀个MDL并不单单包含结构⾥这些东西,在内存中紧接着⼀个MDL结构,存着这个MDL对应的各个物理页⾯编号,由于⼀个物理页⾯⼀定是4KB对齐的,所以这个编号相当于⼀个物理页⾯起始地址的⾼20位。

INFORMIX-体系

INFORMIX-体系

Informix动态服务器采用的是一种多线索体系结构,这就意味着一个进程利用自己的多个线索可以同时完成多个任务,因而整个系统只需要较少的进程就足以完成DBMS的任务。

动态服务器系统由三个主要组件构成:共享内存,进程和磁盘。

共享内存包括三个段:驻留段。

虚拟段和消息段。

驻留段主要用作磁盘数据的缓存。

虚拟段主要用作内存池以支持进程及相关的会话(session)和线索。

当客户与服务器利用共享内存进行通信时,消息段将用作两者之间的消息缓冲区。

系统中还包括若干构成数据库服务器的UNIX进程,称为oninit.这些进程被称为虚拟处理器(VP)(virtual processors)。

每一VP隶属于某一虚拟处理类。

而每一虚拟处理器类都负责完成一类特定的任务。

系统的磁盘组件由多个原始磁盘空间组成,称为chunk,chunk以页(page)为基本单位。

多个chunk集合逻辑上构成了数据空间(dbspace)。

数据空间用于存储数据库、表、系统信息以及物理日志和逻辑日志。

一个数据空间至少包括一个chunk.共享内存段动态服务器的共享内存由三个段构成:驻留段主要用作缓冲池,内含逻辑日志和物理日志的缓冲区以及其他系统数据结构。

驻留段的大小主要有系统参数BUFFERS决定。

虚拟段主要用作内存池以支持会话和线索。

根据用途的不同,内存池可以进一步分为:会话池、多线索池、字典池、存储过程池、排序池、大缓冲池以及全局池。

内存池的分配和释放是动态进行的。

内存池分配单位大小为8k。

如果已有虚拟段耗尽,动态服务器可以根据onconfig参数再次动态申请。

虚拟内存段的初始大小由参数SHMVIRTSIZE决定,其增量由参数SHMADD决定,但整个共享内存段的大小不能超过SHMTOTAL。

如果客户与服务器利用共享内存进行通讯,消息段将用作通讯缓冲区。

每一用户连接(利用共享内存进行通讯)大致占用12K空间。

用户连接的数量在参数NETTYPE中定义。

内存表功能说明

内存表功能说明

内存表功能说明一、功能实现内存表实现了数据库的简单功能,他没有单独的程序,而是作为了scf的一个模块,对内存表的命令控制不像INFORMIX有DBACCESS,ORACLE有SQLPLUS界面,而是用原来控制SCF的INACCESS程序;另外,内存表对SQL语句的支持也不像数据库那样强大,内存表可以理解成实现了简单的sql语句的简单数据库。

二、与数据库的区别内存表与数据库的区别就是,他表里的内容,完全是放在内存里的,故查询起来变得比数据库要快;另外,内存表是把第一个字段固定的作为索引的,且不能添加索引。

三、支持的命令1、memtab tables显示所有表的名称2、memtab desc <tablename>这个命令是仿照的Oracle,是显示指定表的所有字段的名称,类型,是否唯一,desc 也可以写成describe。

3、memtab version显示内存表的版本,以后如果维护,可能会改变存储文件的数据结构,如果数据结构变化以后,如果读取不是同样结构的表文件,会有问题,故表文件里都保存了一个版本。

4、memtab export <tablename>将一个表的内容导出放到一个与表的名字同名的文本文件,该文件的第一行使创建表的SQL语句,第二行及以后的内容才是真正的表的内容。

字段之间用’|’隔开,字段之间用’\n’隔开。

5、memtab import <filename>讲一个文件的内容导入表,是ememtab export的逆过程,注意第一行必须是创建表的SQL语句,生成的表名与文件名并不一定一致,与第一行的CREATE sql 有关6、memtabe wcount [number]当执行Insert,Delete,Update语句时,并不是没执行一次都要写一次文件,这样太慢了,而是执行一定数量的Insert,Delete或Update时才写一遍文件,这个命令可以设置这个数量。

3. MicroStation_MDL

3. MicroStation_MDL

15 |
© 2009 Bentley Systems, Incorporated
在VS中调试MDL
启动MS V8i; 切换到VS中,设置断点; 在VS中选菜单Debug > Attach to Process 在Attach to Process对话框中设置Attach to 为NativeCode,然后选择 ustation.exe进程并点击Attach按钮 再切换到MS V8i,装载你的MDL程序,此时,自动进入VS调试环境 其它步骤详见VS的使用说明
9 |
© 2009 Bentley Systems, Incorporated
10 |
Questions ?
© 2009 Bentley Systems, Incorporated
3. NativeCode程序的生成、运行、分析和调试
© 2009 Bentley Systems, Incorporated
MDL开发
——用C/C++开发MicroStation应用程序
Bentley开发商网络(BDN)工程师 符永安 yongan.fu@
1. 两种MDL开发模式介绍 2. MDL程序开发流程
3. NativeCode程序的生成、运行、分析和调试
Table CT_MAIN = { } Table CT_ACTION = { { 1, CT_ACTYPE, } INHERIT, NONE, "ACTION" },
© 2009 Bentley Systems, Incorporated
{ 1, CT_ACTION, PLACEMENT, REQ,
如果希望达到想开发Addins那样在VS环境中直接编译,请参考 《在VS中手工建立MDL项目.pdf》中描述的详细步骤。

驱动设备读写即通信方式

驱动设备读写即通信方式
// 完成 IRP //设置 IRP 完成状态 pIrp->IoStatus.Status = status;
//设置 IRP 操作了多少字节 pIrp->rmation = ulReadLength; // bytes xfered
南邮王下邀月熊_驱动学习之驱动设备读写
读写方式 DO_BUFFERED_IO
缓冲区地址 Irp->AssociatedIrp.SystemBuffer
DO_DIRECT_IO
缓冲区长度:
length

stack->Parameters.Read.Length;
或者:
length

stack->Parameters.Write.Length;
int main() {
HANDLE hDevice = CreateFile("\\\\.\\HelloDDK",
南邮王下邀月熊_驱动学习之驱动设备读写
GENERIC_READ | GENERIC_WRITE,
0,
// share mode none
NULL, // no security
OPEN_EXISTING,
Irp->MdlAddress
缓冲区设备读写:
以缓冲区方式读写设备时候,操作系统会将 WriteFile 提供的用户模式的缓冲区复制到 内核模式地址下,有 WriteFile 创建的 IRP 的 AssociatedIrp.SystemBuffer 子域记录。
Ring3 层程序: #include <windows.h> #include <stdio.h>
pIrp->IoStatus.Status = status;

ARM指令里几个特殊符号.

ARM指令里几个特殊符号.

ARM指令里几个特殊符号ARM指令里几个特殊符号类别:嵌入式系统作者:孙晓明, 华清远见嵌入式学院讲师。

总结一下ARM指令里几个特殊符号的意义特殊符号对应指令含义 = DCB分配一片连续的字节存储单元并用指定的数据初始化& DCD 分配一片连续的字存储单元并用指定的数据初始化%SPACE 分配一片连续的存储单元^ MAP 定义一个结构化内存表的首地址# FILED 定义一个结构化内存表的数据域(经常和MAP一起使用,一个定义起始地址,一个定义长度) EQU 为程序中的常量、标号等定义一个等效的字符名称,类似于C语言中的#define! 地址更新[相当于IF|相当于ELSE]相当于ENDIF 常见的数据定义伪指令有如下几种:— DCB 用于分配一片连续的字节存储单元并用指定的数据初始化。

— DCW ( DCWU )用于分配一片连续的半字存储单元并用指定的数据初始化。

— DCD ( DCDU )用于分配一片连续的字存储单元并用指定的数据初始化。

— DCFD( DCFDU )用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。

— DCFS ( DCFSU )用于为单精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。

— DCQ ( DCQU )用于分配一片以 8 字节为单位的连续的存储单元并用指定的数据初始化。

— SPACE 用于分配一片连续的存储单元— MAP 用于定义一个结构化的内存表首地址— FIELD 用于定义一个结构化的内存表的数据域1、 DCB 语法格式:标号 DCB 表达式 DCB 伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。

其中,表达式可以为 0 ~ 255 的数字或字符串。

DCB 也可用“ = ” 代替。

使用示例:Str DCB “ This is atest ! ” ;分配一片连续的字节存储单元并初始化。

2、 DCW(或DCWU)语法格式:标号 DCW (或 DCWU )表达式 DCW (或 DCWU )伪指令用于分配一片连续的半字存储单元并用伪指令中指定的表达式初始化。

驱动使用MDL方式读写内存

驱动使用MDL方式读写内存

驱动使⽤MDL⽅式读写内存背景通常,我们在内核中修改内存的时候,都是通过修改 CR0 寄存器,关闭内存写保护属性,然后再写⼊内存的⽅式来修改内存。

我个⼈不喜欢这种⽅式,因为总感觉我们使⽤没有线程接⼝函数的⽅法,总感觉不太稳定,⽽且,在 64 位程序下,CR0 ⽅式不再适⽤了。

所以,我强烈推荐在内核下使⽤ MDL ⽅式来修改内存,在 32 位内核和 64 位内核下同样有效。

内存描述符列表 (MDL) 是⼀个系统定义的结构,通过⼀系列物理地址描述缓冲区。

MDL的全称是 Memory Descriptor List,即内存描述符表。

可以通过MDL描述⼀块内存区域,在MDL中包含了该内存区域的起始地址、拥有者进程、字节数量、标记等信息。

MDL 是⽤来建⽴⼀块虚拟地址空间与物理页⾯之间的映射。

对这句话的理解是使⽤ MDL 来修改内核内存的关键。

当我们要对⼀块内核内存进⾏修改的时候,我们先为这块内存创建 MDL,那么就会建⽴⼀块新的虚拟内存空间,与将要修改内存对应的物理空间相映射。

也就是说,同⼀块物理空间,映射了两块不同的虚拟内存地址。

我们可以通过这两个虚拟内存地址,来操作这块物理内存,这便是 MDL 修改内存的实现思路。

那么,使⽤ MDL ⽅式修改内存具体的实现流程如下:⾸先,给定缓冲区的起始地址和长度,调⽤ MmCreateMdl 函数分配⼀个⾜够⼤的 MDL 结构来映射给定的缓冲区然后,调⽤ MmBuildMdlForNonPagedPool 函数来更新 MDL 对物理内存的描述。

最后,调⽤ MmMapLockedPages 函数将 MDL 中描述的物理页⾯映射到虚拟内存中,并返回映射的虚拟内存地址,这样我们就可以通过新映射的虚拟内存地址,操作同⼀块物理页⾯了,以此实现修改指定内存的数据。

代码:BOOLEAN MDLWriteMemory(PVOID pBaseAddress, PVOID pWriteData, SIZE_T writeDataSize){PMDL pMdl = NULL;PVOID pNewAddress = NULL;// 创建 MDLpMdl = MmCreateMdl(NULL, pBaseAddress, writeDataSize);if (NULL == pMdl){return FALSE;}// 更新 MDL 对物理内存的描述MmBuildMdlForNonPagedPool(pMdl);// 映射到虚拟内存中pNewAddress = MmMapLockedPages(pMdl, KernelMode);if (NULL == pNewAddress){IoFreeMdl(pMdl);}// 写⼊数据RtlCopyMemory(pNewAddress, pWriteData, writeDataSize);// 释放MmUnmapLockedPages(pNewAddress, pMdl);IoFreeMdl(pMdl);return TRUE;}。

【驱动笔记14】初步认识MDL

【驱动笔记14】初步认识MDL

【驱动笔记14】初步认识MDL学习各种高级外挂制作技术,马上去百度搜索"魔鬼作坊",点击第一个站进入,快速成为做挂达人。

前段时间在群里有人问起什么是MDL,当时三言两语也不知道解释清楚了没,今天闲着无事,索性记录下来吧,就当是做个笔记,以后忘了也好查阅。

我们知道,系统中一些重要的表项如SSDT是只读的,如果我们强行对其进行修改就会造成BSOD的严重后果。

当然这种保护方式很容易被绕过,我们曾经介绍了通过修改cr0来禁用WP(Write Protect,写保护)位的方法,现在再介绍一种不需要使用汇编的方法,就是MDL。

MDL的全称是Memory Descriptor List,即内存描述符表。

我们可以通过MDL描述一块内存区域,在MDL中包含了该内存区域的起始地址、拥有者进程、字节数量、标记等信息,如下所示:typedef struct_MDL{struct_MDL*Next;CSHORT Size;CSHORT MdlFlags;struct_EPROCESS*Process;PVOID MappedSystemVa;PVOID StartVa;ULONG ByteCount;ULONG ByteOffset;}MDL,*PMDL;我们先来看一段在SSDT HOOK中常见的代码,如下所示:PMDL MDSystemCall;PVOID*MappedSCT;MDSystemCall=MmCreateMdl(NULL,KeServiceDescriptorTable.ServiceTableBase,K eServiceDescriptorTable.NumberOfServices*4);if(!MDSystemCall){return STATUS_UNSUCCESSFUL;}MmBuildMdlForNonPagedPool(MDSystemCall);MDSystemCall->MdlFlags|=MDL_MAPPED_TO_SYSTEM_VA;MappedSCT=MmMapLockedPages(MDSystemCall,KernelMode);HookOn(ZwTerminateProcess,New_ZwTerminateProcess);其中KeServiceDescriptorTable描述的是SSDT,其中ServiceTableBase标明了SSDT的起始地址,因此我们通过MmCreateMdl函数创建一个MDL,它刚好把SSDT这块内存包含在内,有人可能会问,它的长度为啥是“KeServiceDescriptorTable.NumberOfServices*4”字节呢?很简单,因为指针的长度是4个字节。

DQL,DML, DDL,DCL区别

DQL,DML, DDL,DCL区别

SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL。

其中用于定义数据的结构,比如创建、修改或者删除数据库;DCL用于定义数据库用户的权限;在这篇文章中我将详细讲述这两种语言在Oracle中的使用方法。

DML语言DML是SQL的一个子集,主要用于修改数据,下表列出了ORACLE支持的DML语句。

语句用途INSERT 向表中添加行UPDATE 更新存储在表中的数据DELETE 删除行SELECT FOR UPDATE 禁止其他用户访问DML语句正在处理的行。

LOCK TABLE 禁止其他用户在表中使用DML语句插入数据INSERT语句常常用于向表中插入行,行中可以有特殊数据字段,或者可以用子查询从已存在的数据中建立新行。

列目录是可选的,缺省的列的目录是所有的列名,包括comlumn_id,comlumn_id可以在数据字典视图ALL_TAB_COLUMNS,USER_TAB_COLUMNS,或者DBA_TAB_COLUMNS中找到。

插入行的数据的数量和数据类型必须和列的数量和数据类型相匹配。

不符合列定义的数据类型将对插入值实行隐式数据转换。

NULL字符串将一个NULL值插入适当的列中。

关键字NULL常常用于表示将某列定义为NULL值。

下面的两个例子是等价的。

INSERT INTO customers(cust_id,state,post_code)VALUE('Ariel',NULL,'94501');或INSERT INTO customers(cust_id,state,post_code)VALUE('Ariel',,'94501');更新数据UPDATE命令用于修改表中的数据。

UPDATE order_rollupSET(qty,price)=(SELECT SUM(qty),SUM(price) FROM order_lines WHERE customer_id='KOHL' WHERE cust_id='KOHL'AND order_period=TO_DATE('01-Oct-2000')删除数据DELETE语句用来从表中删除一行或多行数据,该命令包含两个语句:1、关键字DELETE FROM后跟准备从中删除数据的表名。

硬盘MDL解析

硬盘MDL解析

硬盘MDL号解析希捷硬盘各型号数字代表的意思:此款硬盘的编号为ST3120026AS。

前两位字母“ST”表示希捷。

“ST”后面的每一位数字“3”表示硬盘的外现,希捷硬盘的外型主要有以下几种,分别用数字“1、3、4、5、9”来表示:1 -代表3.5英寸全高硬盘,厚度:41mm3 -代表3.5英寸半高硬盘,厚度:25mm4 -代表现在已被淘汰的5.25英寸硬盘。

厚度:82mm5 -代表3.5英寸硬盘,厚度:19mm9 -代表2.5英寸半高硬盘。

这款产品的第一位数字为“3”,也就代表是采用了3.5英寸半高硬盘,厚度:25mm的盘体。

从第2位数字开始,至第5位结束,也就是2-3-4-5位,代表硬盘容量,单位为100M。

当然百GB以下的硬盘就是2-3-4位。

1200表示:1200 × 100M=120G800表示:800 × 100M=80G第6位和第7位数字,也就是6-7位,代表硬盘标志,由主标志和副标志组成。

第一位表示在普通IDE硬盘中的盘片数,如这里为“2” ,表示此盘由两张盘片组成;第二位只在在主标志相同或无效时才有用,表示硬盘的代数,数字越大,代数越高,即此硬盘越新。

而在Seagate的SCSI硬盘中,其主标识则是指硬盘的转速了。

8位:由1到3个字母组成,代表硬盘接口类型。

A -代表:Ultra ATA,即普通IDE/EIDE接口,这是大多数桌面硬盘所采用的接口类型;AS -代表:Serial ATA,即 SATA 硬盘接口。

AG -代表:笔记本电脑专用的ATA的接口(以下都是不常用的:)N -代表:50针Ultra SCSI的接口,其数据传输率为20MB/sW -代表:68针Ultra SCSI接口,其数据传输率为40MB/sWC -代表:80针Ultra SCSI的接口FC -代表:光纤,可提供高达100MB/s的数据传输率,并且支持热拔插WD -代表:68针Ultra Wide SCSI的接口LW -代表:68针Ultra-2 SCSI(LVD)的接口LC -代表:80针Ultra-2 SCSI(LVD)的接口西部数据(West Digital)硬盘的编号规则WD表示西部数据West Digital的简写,从WD后的第一位数字至第四字,代表的是这款硬盘的容量,单位为100M,与ST相同。

NT驱动

NT驱动

理解Windows NT驱动程序最重要的概念之一就是驱动程序运行时所处的“执行上下文”。

理解并小心地应用这个概念可以帮助你构建更快、更高效的驱动程序。

NT标准内核模式驱动程序编程中的一个重要观念是某个特定的驱动程序函数执行时所处的“上下文”。

传统上文件系统开发者最关注这个问题,但所有类型的NT内核模式驱动程序的编写者都能从对执行上下文的深刻理解中获益。

小心谨慎地使用执行上下文的概念能帮助构建更高性能、更低开销的驱动程序设计。

在本文中,我们将探寻执行上下文的概念。

作为对概念的示范,本文在结尾描述了一个能让用户程序在内核模式下运行并拥有其中所有权限的驱动程序。

在这个过程中,我们也将讨论设备驱动程序中执行上下文的实际用法。

什么是上下文?当提及一个例程的上下文时,我们是指它的线程和进程的执行环境。

在NT中,这个环境由当前的线程环境块(TEB)和进程环境块(PEB)建立。

上下文因此包括虚拟内存的设置(告诉我们那个物理内存页面对应那个虚拟内存地址),句柄转换(因为句柄是基于进程的),分派器信息,堆栈,以及通用和浮点寄存器的设置。

当我们问到一个特定的内核例程运行在那个上下文时,我们实际在问,“那一个是(NT内核)分派器建立的当前线程?”因为每一个线程只属于一个进程,当前线程确定了当前进程。

当前线程和当前进程在一起确定了唯一标识线程和进程的所有事情(句柄、虚拟内存、调度器状态和寄存器)。

虚拟内存也许是上下文中对内核模式驱动程序编写者最有用的一个方面。

还记得NT把用户进程映射到虚拟地址空间的低2GB,把操作系统自身的代码映射到虚拟地址空间的高2GB吗?当一个用户进程中的线程执行时,它的虚拟地址范围是0到2GB,2GB以上的所有地址均被设置为“no access”,以此防止用户直接访问操作系统代码和结构。

当操作系统代码执行时,它的虚拟地址范围是2到4GB,而当前用户进程(如果有的话)的地址映射到0到2GB。

在NT3.51和V4.0中,映射到高2GB地址的代码从不变化。

一文搞懂数据库锁知识

一文搞懂数据库锁知识

⼀⽂搞懂数据库锁知识⽂章已收录我的仓库:数据库锁知识(INNODB)库锁库锁主要分为两类:FTWRL(Flush tables with read lock),将数据库设置为只读状态,当客户端异常断开后,该锁⾃动释放,官⽅推荐使⽤的库锁。

设置global全局变量,即set global readonly=true,同样是将数据库设置为只读状态,但⽆论何时,数据库绝不主动释放锁,即时客户端异常断开连接。

Flush tables with read lock 具备更安全的异常处理机制,因此建议使⽤Flush tables with read lock⽽不是修改全局变量。

表锁约定:为了⽅便,⽂章将SELECT语句归于MDL语句。

MDL锁MDL锁,是⼀种表锁,也称元数据锁(metadata lock),元数据锁是server层的锁,MYSQL下的所有引擎⼏乎都提供表级锁定,表级锁定分为表共享读锁(S锁)与表独占写锁(X锁)。

在我们执⾏DDL语句时,诸如创建表、修改表数据等语句,我们都需要申请表锁以防⽌DDL语句之间出现的并发问题,只有S锁与S锁是共享的,其余锁都是互斥的,这种锁不需要我们显⽰的申请,当我们执⾏DDL语句时会⾃动申请锁。

当然我们也可以显⽰的申请表锁:LOCK TABLE table_name READ;使⽤读锁锁表,会阻塞其他事务修改表数据,⽽对读表共享。

LOCK TABLE table_name WRITE;使⽤写锁锁表,会阻塞其他事务读和写。

MDL锁主要⽤于解决多条DDL语句之间的并发安全问题,但除了DDL与DDL之间的问题,DDL与DML语句之间也会出现并发问题,因此INNODB下,还会存在⼀种隐式的上锁⽅式。

意向锁事实上,为解决DDL和DML之间的冲突问题,在INNODB下,数据库还会为每⼀条DML语句隐式地加上表级锁,这并不需要我们显⽰的指定。

来看看数据库为什么这么做,我们假设事务A执⾏⼀条DDL语句ALTER TABLE test DROP COLUMN id;,⽽事务B正在执⾏两条DML语句SELECT * FROM,如果对数据库⽐较了解,你应该很快的就会发现其中存在⼀些并发安全问题:事务A事务BBEGIN BEGINSELECT * FROM test;...ALTER TABLE test DROP COLUMN id;SELECT * FROM test;COMMIT COMMIT这就产⽣了冲突现象,事务A执⾏的两条查询语句不⼀致,违背了事务的⼀致性,⽽为了解决这个问题,MYSQL引⼊了意向锁,官⽅将这种锁分为意向共享锁(IS锁)和意向排他锁(IX锁),意向锁是由DML操作产⽣的,请注意区分与上⽂所说的S锁与X锁,意向共享锁表明当前表上存在某⾏记录持有⾏共享锁(区别表S锁),意向排他锁表明当前表上存在某⾏记录持有⾏排他锁(区别表X锁)。

文件描述符通俗解释

文件描述符通俗解释

文件描述符通俗解释1.引言1.1 概述文件描述符是操作系统中对文件、流以及其他I/O资源的唯一标识符。

它是一个非负整数,通常被用来表示一个被打开文件的索引或者指针。

在操作系统中,文件描述符作为一个抽象概念,用于管理对文件的访问。

通过文件描述符,操作系统可以对文件进行读写操作,实现数据的输入和输出。

文件描述符的作用在于提供程序与操作系统之间的接口。

通过文件描述符,程序可以与操作系统进行交互,申请文件资源以及进行读写操作。

在程序中,通过打开文件或者创建文件时,操作系统会为其分配一个文件描述符。

程序通过操作文件描述符来读取和写入文件的内容,从而实现数据的读写功能。

文件描述符可以看作是一个指向文件的指针,操作系统使用它来追踪文件的状态和位置。

通过文件描述符,操作系统可以将多个进程同时访问同一个文件,保证数据的一致性和安全性。

同时,文件描述符也提供了对文件进行操作的方式,例如打开、关闭、读取和写入等。

在操作系统中,文件描述符的分类主要分为标准文件描述符、用户文件描述符和网络文件描述符。

标准文件描述符是由操作系统预先定义的,分别用来表示标准输入、标准输出和标准错误输出。

用户文件描述符是由程序员在代码中创建的,用于访问文件和流。

网络文件描述符则是用于网络通信中,表示网络连接或套接字。

因此,文件描述符在操作系统中起到了连接程序和操作系统的桥梁作用。

它提供了对文件和I/O资源的访问接口,方便程序与操作系统进行交互。

了解和理解文件描述符的定义和作用对于程序开发和系统管理都十分重要。

在接下来的章节中,我们将进一步探讨文件描述符的分类以及它的重要性和应用场景。

1.2文章结构文章结构主要分为引言、正文和结论三个部分。

引言部分介绍了文章的背景和目的。

在我们的文章中,引言分为三个小节:概述、文章结构和目的。

1.1 概述:在这一小节中,我们将简单介绍文件描述符的概念和作用。

文件描述符是计算机操作系统中用于访问文件或其他资源的抽象概念。

Mysql中的MDL

Mysql中的MDL

Mysql中的MDL本⽂可以结合查看。

⾸先简单了解⼀下 mysql 的 sql 类型:1、数据定义语⾔ DDL:Create、Drop、Alter 操作。

⽤于定义库和表结构的。

2、数据查询语⾔ DQL:select。

⽤于查询数据的。

3、数据操纵语⾔ DML:insert、update、delete。

对⾏记录进⾏增删改操作。

4、数据控制语⾔ DCL:grant、revoke、commit、rollback。

控制数据库的权限和事务。

MDLMDL(MetaData Lock)就是针对于 DDL 与 DML、DQL 操作加锁,执⾏ DDL ⾃动添加写锁,执⾏ DML、DQL ⾃动添加读锁,也就是说 DML 语句可以同时执⾏(不考虑其他锁),⽽DDL 间则会相互阻塞。

为什么在执⾏ DDL 时会添加写锁?DDL 在执⾏会先创建⼀个临时表,先将表的数据全部移到这个临时表中,然后再将临时表替换当前表。

在这个过程中如果出现读写操作就会影响最终结果出错。

这个过程耗时主要在将原表的数据移到临时表的过程。

执⾏不同事务的执⾏是按队列顺序进⾏的,如果两个事务所执⾏的 MDL 添加的分别是读、写锁,那么就会互斥,后⾯的事务只有等到前⾯事务提交释放锁后才能执⾏。

例⼦:假设有四个会话:session1、session2、session3、session4 ,⾸先先依次开启事务,然后session1,session2 先执⾏查询操作(为了避免可能是可串⾏化级别导致加的写锁冲突,所以就使⽤查询操作),session1,session2 中的操作可以正常执⾏,session3执⾏ Alter 修改表结构,此时 session3 的操作就会阻塞(因为 MDL 的读写锁冲突),session4 再执⾏增删改查也会被阻塞,因为是在队列中,它位于 session3 后⾯,所以只有等到 session3 提交后其才能继续执⾏。

Online DDL通过上⾯的分析,进⾏实践检验,却出现了下⾯的情况:可以看到执⾏和显⽰顺序是图中标注的从1开始递增按顺序执⾏的。

Windows内核开发-7-IRP和派遣函数

Windows内核开发-7-IRP和派遣函数

Windows内核开发-7-IRP和派遣函数Windows内核-7-IRP和派遣函数IRP以及派遣函数是Windows中⾮常重要的概念。

IRP 是I/O Request Pocket的简称,意思是I/O操作的请求包,Windows中所有User和Kernel之间的交流都会被封装成⼀个IRP结构体,然后不同的IRP会被派遣到不同的派遣函数⾥⾯,通过派遣函数来实现I/O操作。

IRPtypedef struct _IRP {CSHORT Type;USHORT Size;PMDL MdlAddress;ULONG Flags;union {struct _IRP *MasterIrp;__volatile LONG IrpCount;PVOID SystemBuffer;} AssociatedIrp;LIST_ENTRY ThreadListEntry;IO_STATUS_BLOCK IoStatus;KPROCESSOR_MODE RequestorMode;BOOLEAN PendingReturned;CHAR StackCount;CHAR CurrentLocation;BOOLEAN Cancel;KIRQL CancelIrql;CCHAR ApcEnvironment;UCHAR AllocationFlags;union {PIO_STATUS_BLOCK UserIosb;PVOID IoRingContext;};PKEVENT UserEvent;union {struct {union {PIO_APC_ROUTINE UserApcRoutine;PVOID IssuingProcess;};union {PVOID UserApcContext;#if ..._IORING_OBJECT *IoRing;#elsestruct _IORING_OBJECT *IoRing;#endif};} AsynchronousParameters;LARGE_INTEGER AllocationSize;} Overlay;__volatile PDRIVER_CANCEL CancelRoutine;PVOID UserBuffer;union {struct {union {KDEVICE_QUEUE_ENTRY DeviceQueueEntry;struct {PVOID DriverContext[4];};};PETHREAD Thread;PCHAR AuxiliaryBuffer;struct {LIST_ENTRY ListEntry;union {struct _IO_STACK_LOCATION *CurrentStackLocation;ULONG PacketType;};};PFILE_OBJECT OriginalFileObject;} Overlay;KAPC Apc;PVOID CompletionKey;} Tail;} IRP;IRP这种机制类似于Windows的消息机制,驱动在接受到IRP之后会根据IRP的不同类型分配给不同类型的派遣函数来处理IRP。

详解ARM处理器中的37个寄存器

详解ARM处理器中的37个寄存器

详解ARM处理器中的37个寄存器ARM处理器共有37个寄存器。

其中包括:31个通用寄存器,包括程序计数器(PC)在内。

这些寄存器都是32位寄存器。

6个状态寄存器。

这些寄存器都是32位寄存器。

ARM处理器共有7种不同的处理器模式,每一种模式中都有一组相应的寄存器组。

在任何时刻,可见的寄存器包括15个通用寄存器(R0-R14),一个或两个状态寄存器及程序计数器(PC)。

在所有的寄存器中,有些是各模式公用一个物理寄存器,有一些寄存器各模式拥有自己独立的物理寄存器。

通用寄存器:通用寄存器分为以下三类:备份寄存器、未备份寄存器、程序计数器PC未备份寄存器:未备份寄存器包括R0-R7。

对于每一个未备份寄存器来说,所有处理器模式下都是使用同一个物理寄存器。

未备份寄存器没有被系统用于特别的用途,任何可采用通用寄存器的场合都可以使用未备份寄存器。

备份寄存器:对于R8-R12备份寄存器来说,每个寄存器对应两个不同的物理寄存器。

系统为将备份寄存器用于任何的特殊用途,但是当中断处理非常简单,仅仅使用R8-R14寄存器时,FIQ处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理非常迅速。

对于R13,R14备份寄存器来说,每个寄存器对应六个不同的物理寄存器,其中的一个是系统模式和用户模式共用的;另外的五个对应于其他的五种处理器模式。

采用下面的记号来区分各个物理寄存器:R13_其中MODE可以是下面几种模式之一:usr,svc,abt,und,irq,fiq程序计数器PC可以作为一般的通用寄存器使用,但有一些指令在使用R15时有一些限制。

由于ARM采用了流水线处理器机制,当正确读取了PC的值时,该值为当前指令地址值加上8个字节。

也就是说,对于ARM指令集来说,PC指向当前指令的下两条指令的地址。

由于ARM指令是字对齐的,PC值的第0位和第一位总为0。

需要注意的是,当使用str/stm保存R15时,保存的可能是当前指令地址值加8个字节,也可能保存的是当前指令地址值加12个字节。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MDL(内存描述符表)详解
分类:初学驱动2013-01-25 18:07 308人阅读评论(0) 收藏举报mdl
以下的虚拟内存可以理解成逻辑内存,因为我觉得只有这样才能讲通下面所有的东西。

以下的“未分页”指没有为页进行编码。

以下为MDL结构体(我很郁闷,我在MSDN上没有找到这个结构体)
typedef struct _MDL {
struct _MDL *Next; //下一个MDL
CSHORT Size; //大小
CSHORT MdlFlags; //标志,保护属性等
struct _EPROCESS *Process;//
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
如何使用MDL:
一个连续的虚拟内存地址范围可能是由多个分布(spread over)在不相邻的物理页所组成的。

系统使用MDL(内存描述符表)结构体来表明虚拟内存缓冲区的物理页面布局。

我们应该避免直接访问MDL。

我们可以使用MS-Windows提供的宏,他们提供了对这个结构体基本的访问。

·MmGetMdlVirtualAddress 获取缓冲区的虚拟内存地址
·MmGetMdlByteCount 获取缓冲区的大小(字节数)
·MmGetMdlByteOffset 获取缓冲区开端的物理页的大小(字节数)·MmGetMdlPfnArray 获取记录物理页码的一个数组指针。

我们可以用IoAllocateMdl函数来分配一个MDL。

如果要取消分配,可是使用IoFreeMdl 函数。

或者,可以使用MmInitializeMdl来把一个之前定义的缓冲区定制成一个MDL。

但是以上两种方式都不能初始化物理页码数组。

对于在未分页池中分配的缓冲区,可以用MmBuidlMdlForNonpagedPool函数来初始化页码数组。

对于可分页的内存,虚拟内存和物理内存之间的联系是暂时的,所以MDL的页码数组只在特定的环境和时间段有效,因为很可能其他的程序对它们进行重新分配,为了使其
他的程序无法对他们进行修改和重新分配(在我们释放之前),我们就需要把这段内存锁定,防止其他程序修改,我们可以用MmProbeAndLockPages来实现,这个函数同时还为当前的布局初始化了页码数组。

当我们用MmUnlockPages来释放被锁定的内存时,页码数组也会随之无效。

假如MDL指定的是映射一块内核级别的虚拟地址空间,那么我们要用MmGetSystemAddressForMdlSafe ,这样我们就能防止映射目标是来自用户模式的空间,而来自用户模式空间的物理页只能在用户模式上下文环境中使用,并且随时可能被清空。

用函数进行申明后,就可以防止以上情况发生了。

以下这个函数是用于新创建一个MDL的:参数详解可翻阅MSDN
PMDL IoAllocateMdl(
IN PVOID VirtualAddress,
IN ULONG Length,
IN BOOLEAN SecondaryBuffer,
IN BOOLEAN ChargeQuota,
IN OUT PIRP Irp OPTIONAL
);
最后一个参数是指IRP(输入输出请求包),也就是将新建的这个MDL缓冲区和指定的IRP 关联,为什么要关联?举个例子,比如网络驱动中就应该为每一个发送到本机的IP数据报建立一个临时缓冲区,而最终用户——应用程序要读取这个缓冲区的数据,必须使用IRP
请求驱动程序来完成,所以要提取某个IP数据报,只要发送相关IRP给驱动程序,驱动程序遍历其创建的MDL链找到相应的MDL,然后进行数据提取和发送,请求处理完之后,驱动程序会自动清除这个MDL。

一个IRP可以关联多个MDL,就像上面举的例子一样,一个IRP 关联到多个IP数据报(也就是多个MDL)。

当应用成语的某个IRP要求一个新的请求(可能是一个新的IP地址的IP数据报)时,驱动程序发现没有MDL与之联,这个时候该IP发送来一个IP数据报,这时驱动程序便建立一个MDL与之关联,如果这是第一个新建的与这个IRP关联的MDL,那么驱动程把该MDL的地址赋值给MdlAddress。

如果不是第一个,那么将把新建的MDL放到上一个MDL的下一个单位,形成MDL 链。

这就是MDL结构体中的第一个成员的含义所在。

总结:MDL就是描述一块虚拟内存的结构体,里面有个成员记录了多个页码,这些页码即处于各个不同物理地址的物理块的页号。

所以要对一块受系统保护的区域进行写操作的话,可以这样来修改它的保护属性:
1.创建一个MDL,显然里面的物理页号数组没有初始化 IoAllocateMdl
2.初始化页码数组,使之成为实际有效的MDL MmBuildMdlForNonPagedPool
3.进行锁定,并且重新赋值新的保护属性为可读 MmProbeAndLockPages
4.获得我们所映射后的实际内存区域的虚拟地址 MmMapLockedPagesSpecifyCache
网上的很多代码是用于2000和其之前的OS的,很多函数都改了,方式也不一样了,以下代码用于在SSDT表所在的内核区映射一个MDL,并且修改其只读属性为可写的,然后固定这块内存,防止它被其他应用程序修改。

g_pmdlSystemCall =IoAllocateMdl
(KeServiceDescriptorTable.ServiceTableBase,KeServiceDescriptorTable.NumberOfSer vices*4,FALSE,FALSE,NULL);
if(!g_pmdlSystemCall)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(g_pmdlSystemCall);//初始化MDL页码数组
//g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags |
MDL_MAPPED_TO_SYSTEM_VA;// 改变MDL的flags为可读状态
MmProbeAndLockPages(g_pmdlSystemCall,KernelMode,IoWriteAccess);//在内存中锁定,并且指
明对它的改写权力
MappedSSDT=MmMapLockedPagesSpecifyCache( //映射被锁定内存,所谓映射,就是创建原来内存区的一个联合体,你
//修改了这个MDL,就是修改了它所描述的内存区
g_pmdlSystemCall,
KernelMode,
MeNonCached,//是否允许用作CPU缓冲区
FALSE,//当第二个参数为UserMode的时候才有效
NULL,//如果发生错误,直接返回NULL
); //MappedSSDT即映射后的SSDT地址
【注意】最后一个函数其实是大材小用了,只不过2000之后能得到映射缓冲区地址的函数中这个函数是最先进的被支持者,2000用的是MmMapLockedPages;。

相关文档
最新文档