1、RtlCopyMemory 、RtlCopyBytes、RtlMoveMemory;

2、RtlZeroMemory、RtlFillMemory;

3、RtlEqualMemory;

4、ExAllocatePool、ExFreePool;

5、New(重载)、Delete操作符

一、内存的复制与移动

1、RtlCopyMemory

作用:把一个缓冲区的内容复制到另一一个缓冲区。

VOID RtlCopyMemory(
    IN VOID UNALIGNED *Destination,
    IN CONST VOID UNALIGNED *Source,
    IN SIZE_T Length
    );

参数:
Destination

指针移动的目的地(也就是要粘贴的地方)。

Source
指针指向的要复制的内存 .
Length
        指定要复制的字节数。
返回值

但是如果内存有互相覆盖的情况可能出错,因为源和目的重叠的部分有可能还没读取就被写入了,要用 RtlMoveMemory 进行移除。

2、RtlCopyBytes

作用:复制给定的字节数从一个位置到另一个地方。

VOID RtlCopyBytes(
    IN PVOID Destination,
    IN CONST VOID *Source,
    IN SIZE_T Length
    );

参数:
Destination

指向目的地的字节(也就是要粘贴的地方)。

Source
        指针指向的复制的内存.
Length

指定要复制的字节数。

返回值

推荐驱动应该使用 RtlCopyMemory 进行常规操作,而不是 RtlCopyBytes 。

3、RtlMoveMemory

作用:从指定内存中复制内存至另一内存里.简称:复制内存。RtlCopyMemory非重叠复制,而RtlMoveMemory是重叠复制

对内存进行要么向前或向后移动,或未对齐,对齐在4字节块,紧随其后的是剩余的字节。

VOID RtlMoveMemory(
    IN VOID UNALIGNED  *Destination,
    IN CONST VOID UNALIGNED *Source,
    IN SIZE_T Length
    );

参数:
Destination

指针移动的目的地(也就是要移到的地方)。

Source
        指针指向的复制的内存.
Length

指定要复制的字节数。

返回值

•内存的“copy”和“move”操作之间的区别在于可否容忍源和目的相重叠。move操作不管源和目的是否重叠。而copy操作在源和目的有任何重叠时不工作。

•“byte” 操作和“memory”操作的区别是操作的间隔尺寸。byte操作保证按字节为单位执行。而memory操作可以在内部使用更大的块,所有这些块的和等于 指定的字节数。这个区别会根据平台的不同而改变,在32位Intel计算机上,byte操作实际上是对应memory操作的宏。但在Alpha平台 上,RtlCopyBytes与RtlCopyMemory是完全不同的函数。

二、内存的填充

1、RtlZeroMemory

作用:用0来填充一块内存区域。

VOID RtlZeroMemory(
    IN VOID UNALIGNED  *Destination,
    IN SIZE_T Length
    );

参数:
Destination

指向一块准备用0来填充的内存区域的开始地址。(也就是要填充的地方)。

Length

准备用0来填充的内存区域的大小,按字节来计算

返回值

2、RtlFillMemory

作用:调用者向提供的缓冲区填满给定的字符。

VOID RtlFillMemory(
    IN VOID UNALIGNED  *Destination,
    IN SIZE_T Length,
    IN UCHAR Fill
    );

参数:
Destination

指针指向的内存(也就是要填充的地方)。

Length 
        指定的字节数(要填充多少(大))
Fill

指定填充内存的值。

返回值

三、内存的比较

1、RtlEqualMemory

作用:对两个内存块进行比较,以确定指定的字节数是相同的。

LOGICAL RtlEqualMemory(
CONST VOID  *Source1,
CONST VOID  *Source2,
SIZE_T Length
    );

参数:
Source1

指针指向一个调用者提供的要比较的内存块。

Source2 

指向调用者提供的内存块的指针相对于Source1的内存块。

Fill

待比较内存的长度,单位为字节。

返回值

返回两块内存相等的字节数,并且如果一致就返回True,否则返回False。

四、内存的分配和释放

1、ExAllocatePool

作用: ExAllocatePool分配池指定类型和返回一个指针指向的内存分配的块。另外:ExAllocatePool程序已经过时了,出口仅为现有的二进制文件。建议使用ExAllocatePoolWithTag代替。 

PVOID ExAllocatePool(
IN POOL_TYPE PoolType,
IN SIZE_T NumberOfBytes
    );

参数:
PoolType

给要分配的内存池指定类型。

NumberOfBytes

指定要分配的字节数。

返回值

如果没有足够的内存空闲池中满足要求,返回NULL。否则,程序返回一个指向分配的内存的指针。

2、ExFreePool

作用:释放一块内存池。

VOID ExFreePool(
IN PVOID P
    );

参数:
P

指定要被收回的内存块地址池。

返回值

四、内存的重载操作符

1、New

作用:重载New,也就是用来分配内存。所以这个函数里面要用到 ExAllocatePool API函数,让其达到重载 New 这个函数不用直接调用 ExAllocatePool 这个API函数也能分配内存的目的。

void * __cdecl operator new(size_t size,POOL_TYPE PoolType=PagedPool)

{

KdPrint(("global operator new\n"));

KdPrint(("Allocate size :%d\n",size));

return ExAllocatePool(PagedPool,size);

}

2、delete

作用:重载delete,也就是用来释放内存。所以这个函数里面要用到 ExFreePool API函数,让其达到重载 delete 这个函数不用直接调用 ExFreePool 这个API函数也能释放内存的目的。

void __cdecl operator delete(void* pointer) {
KdPrint(("Global delete operator\n"));

ExFreePool(pointer);

}

下面看一段代码

#pragma once
#ifdef _cplusplus
extern "C"
{
#endif
#include <NTDDK.h> //这里包含需要用C方式编译的头文件
//#include <winnt.h> 运行库已包含了,就不需要,如果报错就需要添加此头文件
#ifdef _cplusplus
}
#endif //重载new和delete操作符
//重载new
void * _cdecl operator new(size_t size, POOL_TYPE PoolType = PagedPool){ //操作符重载,否则报错
KdPrint(("global operator new\n"));
KdPrint(("Allocate size :%d\n", size));
return ExAllocatePool(PagedPool, size); //分配内存
} //重载delete
void __cdecl operator delete(void* pointer) {
KdPrint(("Global delete operator\n"));
ExFreePool(pointer);//释放指针
} #pragma INITCODE
VOID MemoryOpe() {
VOID UNALIGNED *d; //有关于WIN64的定义,无符号
VOID UNALIGNED *s;
SIZE_T Length = ; //无符号类型
ULONG ulRet;
char *buffer = new (PagedPool) char[]; //分配111字节指针
delete buffer;
//为s指针分配大小为字节的内核内存
s=ExAllocatePool(PagedPool,Length);
KdPrint(("s=%x \n",(int*)s));
// _asm int 3 db
//为d指针分配大小为字节的内核内存
d=ExAllocatePool(PagedPool,Length);
// __asm int 3 db
KdPrint(("d=%x \n", (int*)d));
//用来填充s指针指向的内存填充长度为Length=8
RtlFillMemory(s,Length,'s');
// __asm int 3 db
KdPrint(("RtlFillMemory 1 \n"));
//复制S指针指向的内容到D地址复制长度为Length=8
RtlCopyMemory(d,s,Length); //memcpy
// __asm int 3
KdPrint(("RtlCopyMemory s to d \n"));
//复制S指针指向的内容到D地址复制长度为Length=8
RtlCopyBytes(d,s,Length);
//判断内存是否一致
ulRet = RtlCompareMemory(d, s, Length); // 返回为1则相等
//RtlEqualMemory(d,s,Length); 在VS下此句编译错误所以就用DDK进行编译和此函数时请用build
if (ulRet == Length){ //如果返回值
KdPrint(("111 D和S 内存块相同.\n"));
}
else{
KdPrint(("111 D和S 内存块不相同\n"));
} //清空S指针指向地址
RtlZeroBytes(s,Length);
ulRet = RtlCompareMemory(d, s, Length);
if (ulRet == Length){ //如果返回值
KdPrint(("222 D和S 内存块相同.\n"));
}
else{
KdPrint(("222 D和S 内存块不相同\n"));
}
ExFreePool(s);
return;
}

建议在驱动入口函数 DriverEntry 函数中的设备加载过程执行后,再调用此内存操作过程。

在虚拟机下执行过程, 首先是填充了S和D相同的数据所以相同, 然后由于清空S所以S和D就不相同了。

最后将尽量用DDK的RtlCompareMemory函数可移植性比较好.

内存操作相关内核 API 的使用的更多相关文章

  1. linux 内存操作相关命令

    清理内存 echo 1 > /proc/sys/vm/drop_caches 查看内存使用情况 free –m 查看内存条数命令: dmidecode |grep -A16 "Memo ...

  2. Linux内存管理 (19)总结内存管理数据结构和API

    专题:Linux内存管理专题 关键词:mm.vaddr.VMA.page.pfn.pte.paddr.pg_data.zone.mem_map[]. 1. 内存管理数据结构的关系图 在大部分Linux ...

  3. C语言学习笔记--内存操作常见错误

    1. 野指针 (1)指针变量中的值是非法的内存地址,进而形成野指针 (2)野指针不是 NULL 指针,是指向不可用内存地址的指针 (3)NULL 指针并无危害,很好判断,也很好调试 (4)C 语言中无 ...

  4. Java API —— IO流(数据操作流 & 内存操作流 & 打印流 & 标准输入输出流 & 随机访问流 & 合并流 & 序列化流 & Properties & NIO)

    1.操作基本数据类型的流     1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出 ...

  5. clients(PV操作共享内核内存进行输入输出分屏) - server(进程间通信)模型实现

    1.拓扑结构 2.PV操作共享内核内存进行输入输出分屏 (1) int semop(int semid,struct sembuf *sops,size_t nsops): 功能描述 操作一个或一组信 ...

  6. Delphi内存操作API函数(备查,并一一学习)

    Delphi内存操作API函数System.IsMemoryManagerSet;System.Move;System.New;System.ReallocMem;System.ReallocMemo ...

  7. 内核开发知识第一讲.内核中的数据类型.重要数据结构.常用内核API函数.

    一丶内核中的数据类型 在内核中.程序的编写不能简单的用基本数据类型了. 因为操作系统不同.很有可能造成数据类型的长度不一.而产生重大问题.所以在内核中. 数据类型都一定重定义了. 数据类型 重定义数据 ...

  8. Javascript操作DOM常用API总结

    基本概念 在讲解操作DOM的api之前,首先我们来复习一下一些基本概念,这些概念是掌握api的关键,必须理解它们. Node类型 DOM1级定义了一个Node接口,该接口由DOM中所有节点类型实现.这 ...

  9. Guava库介绍之集合(Collection)相关的API

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是我写的Google开源的Java编程库Guava系列之一,主要介 ...

随机推荐

  1. c++ 编译期计算 (一)

    编译期就是编译器进行编译,产生.obj文件的所处的那一段时间(如果是广义的编译期,那么一般还包括了链接期,因为现在很多编译器都会自动调用链接器进行链接)执行期就是你执行某个已经链接好的程序的那段时间. ...

  2. QTableWidget简单操作

    使用Qt设计师工具,在窗体上添加Table Widget控件,这样就可以使用ui全局变量来调用该控件了. Table Widget控件的应用 (1)设置列数和行数 //设¦¨¨置?列¢D数ºy和¨ª行 ...

  3. centos mysql 数据存储目录安装位置

    rpm -ql mysql查看安装位置 MYSQL默认的数据文件存储目录为/var/lib/mysql.假如要把目录移到/home/data下需要进行下面几步: 1.home目录下建立data目录 c ...

  4. python之6-4装饰器.md

    装饰器看的说实话真心郁闷,群里一伙计说了好一会,听得一愣一愣的,查了点资料,又自己试了下,算是明白了一些,记录记录=.=更郁闷的是,博客园的markdown标记支持怎么和为知的不匹配,这转过来的文章很 ...

  5. mysql查询unicode字符串

    mysql查询的时候会将\干掉,可以用mysql的like通配符来做like '%\u5f20\u4e09%'变成like '%_u5f20_u4e09%'

  6. IC封装图片认识(二):TO封装图

    TO-18 TO-220 TO-247 TO-264 TO-52 TO-71 TO-72 TO-78 TO-8 TO-92 TO-93 TO-99 TO-263&268 FTO-220 ITO ...

  7. Chrome小技巧:如何下载离线版安装文件

    每当chrome有更新之后,都有不少用户想要下载离线版的安装文件,但苦于找不到下载地址而发愁,其实这个问题很简单,下面我来分享一下方法(仅针对Windows操作系统): 对于稳定版(正式版)Chrom ...

  8. WPF Image触摸移动方法

    1: TouchPoint mPoint = null; 2: double mOffsetX;//水平滚动条当前位置 3: double mOffsetY;//垂直滚动条当前位置 4: bool m ...

  9. C++指针初始化总结

    1.字符指针的初始化 在c语言中 "string"保存的就是首个字符所在的地址  所以可以把 字符串常量"string" 赋值给指针 char *p;  &qu ...

  10. Spark机器学习笔记一

    Spark机器学习库现支持两种接口的API:RDD-based和DataFrame-based,Spark官方网站上说,RDD-based APIs在2.0后进入维护模式,主要的机器学习API是spa ...