当前位置: 首页 > article >正文

3.1.1 ReactOS系统中二叉树创建一个MEMORY_AREA节点

二叉树中创建一个MEMORY_AREA节点:

二叉树中创建一个MEMORY_AREA节点:
MmCreateMemoryArea()
参数AddressSpace是MADDRESS SPACE结构指针,所指向的数据结构代表着一个进程的用 户空间。
参数BaseAddress是个指针,用来给定和返回内存区块的基地址

文章目录

  • 二叉树中创建一个MEMORY_AREA节点:
  • MmCreateMemoryArea()


MmCreateMemoryArea()


/**
 * @name MmCreateMemoryArea
 *
 * Create a memory area.
 *
 * @param AddressSpace
 *        Address space to create the area in.
 * @param Type
 *        Type of the memory area.
 * @param BaseAddress
 *        Base address for the memory area we're about the create. On
 *        input it contains either 0 (auto-assign address) or preferred
 *        address. On output it contains the starting address of the
 *        newly created area.
 * @param Length
 *        Length of the area to allocate.
 * @param Attributes
 *        Protection attributes for the memory area.
 * @param Result
 *        Receives a pointer to the memory area on successful exit.
 *
 * @return Status
 *
 * @remarks Lock the address space before calling this function.
 */

NTSTATUS STDCALL
MmCreateMemoryArea(PMADDRESS_SPACE AddressSpace,
                   ULONG Type,
                   PVOID *BaseAddress,
                   ULONG_PTR Length,
                   ULONG Protect,
                   PMEMORY_AREA *Result,
                   BOOLEAN FixedAddress,
                   ULONG AllocationFlags,
                   PHYSICAL_ADDRESS BoundaryAddressMultiple)
{
   PVOID EndAddress;
   ULONG Granularity;
   ULONG tmpLength;
   PMEMORY_AREA MemoryArea;

   DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %p, "
          "*BaseAddress %p, Length %p, AllocationFlags %x, "
          "FixedAddress %x, Result %p)\n",
          Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
          FixedAddress, Result);

   MmVerifyMemoryAreas(AddressSpace);//检测该AVL树是否存在问题
	//根据Type选择相应的粒度
   Granularity = (MEMORY_AREA_VIRTUAL_MEMORY == Type ? MM_VIRTMEM_GRANULARITY : PAGE_SIZE);
   //if 用户不要求从固定地址处开始分配
   if ((*BaseAddress) == 0 && !FixedAddress)
   {
   //不受给定地址的约束,只要找到一个够大的空隙即可
      tmpLength = PAGE_ROUND_UP(Length);
      //根据用户空间找到一块符合的Area,并返回其首地址
      *BaseAddress = MmFindGap(AddressSpace,
                               tmpLength,
                               Granularity,
                               (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
      if ((*BaseAddress) == 0)
      {
         DPRINT("No suitable gap\n");
         return STATUS_NO_MEMORY;
      }
   }
   else//用户给定了基址,就必须从那儿开始分配
   {
      tmpLength = Length + ((ULONG_PTR) *BaseAddress
                         - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
      *BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity);

      if (AddressSpace->LowestAddress == MmSystemRangeStart &&
          *BaseAddress < MmSystemRangeStart)
      {
        //给定的空间为系统空间,但是地址落在用户空间,严重错误CHECKPOINT;
         CHECKPOINT;
         return STATUS_ACCESS_VIOLATION;
      }

      if (AddressSpace->LowestAddress < MmSystemRangeStart &&
          (ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
      {
        //所要求的区间跨越用户空间和系统空间的分界,严重错误CHECKPOINT;
         CHECKPOINT;
         return STATUS_ACCESS_VIOLATION;
      }
     //测试要分配的区域完全落在指定地址空间内部
      if (BoundaryAddressMultiple.QuadPart != 0)
      {
         EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
         ASSERT(((ULONG_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
      }
			//确认所要求的区间尚术分配
      if (MmLocateMemoryAreaByRegion(AddressSpace,
                                     *BaseAddress,
                                     tmpLength) != NULL)
      {
      //所要求的区间已经分配,失敗
         DPRINT("Memory area already occupied\n");
         return STATUS_CONFLICTING_ADDRESSES;
      }
   }
 //创建MEMORY AREA节点,把这块区域分配出去
   MemoryArea = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
                                      TAG_MAREA);
   RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
   MemoryArea->Type = Type;
   MemoryArea->StartingAddress = *BaseAddress;
   MemoryArea->EndingAddress = (PVOID)((ULONG_PTR)*BaseAddress + tmpLength);
   MemoryArea->Protect = Protect;
   MemoryArea->Flags = AllocationFlags;
   //MemoryArea->LockCount = 0;
   MemoryArea->PageOpCount = 0;
   MemoryArea->DeleteInProgress = FALSE;

	//将所创建节点插入一又树
   MmInsertMemoryArea(AddressSpace, MemoryArea);

   *Result = MemoryArea;

   DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
   return STATUS_SUCCESS;
}

//二叉树中创建-个MEMORY AREA节点
/*
参数AddressSpace是MADDRESS SPACE结构指针,所指向的数据结构代表着一个进程的用 户空间。
参数BaseAddress是个指针,用来给定和返回内存区块的基地址 :
参数Length、Protect的意义 则不言自明。
参数FixedAddress为TRUE说明给定的地址不容改变,为FALSE则表示若不能满足 要求也可以浮动, 。
参数AllocationFlags : 分配标志TopDown ? TopUp
参数BoundaryAddressMultiple此分配不得跨越的物理地址倍数
*/


http://www.kler.cn/news/363777.html

相关文章:

  • QImage和QPixmap
  • docker常用命令整理
  • Bytebase 3.0.0 - AI 助手全面升级
  • 【Kubernetes实战】Kubernetes集群搭建(虚拟机环境,一主两从)
  • 凹凸性和拐点的概念
  • 怎么在线制作拼团活动
  • 【Python 常用脚本及命令系列 7 -- pdf 文件字符搜索 python脚本实现】
  • element 按钮变形 el-button样式异常
  • Html/Vue浏览器下载并重命名文件
  • Effective C++ | 读书笔记 (一)
  • 安全见闻(3)——开阔眼界,不做井底之蛙
  • 从0到1学习node.js(path模块以及HTTP协议)
  • Rust编写硬件抽象层(HAL)服务
  • 世优科技“AI+空间计算”推动消费行业向智能化升级
  • Mycat 详细介绍及入门实战,解决数据库性能问题
  • ESP32-C3实现非易失变量(Arduino IDE )
  • HuggingFace学习与使用①:核心组件、如何使用?
  • 怎么重写equals()方法和hashCode()方法
  • 代码随想录:206. 反转链表
  • vue3移动端可同时上传照片和视频的组件
  • 项目分析:自然语言处理(语言情感分析)
  • 释放双手,让微信聊天更智能 —— 单机版个人微信智能客服软件介绍
  • Redis学习笔记(三)--Redis客户端
  • SpringBoot技术的车辆管理流程自动化
  • 基于SSM+微信小程序的酒店管理系统1
  • Java项目-基于springboot框架的自习室预订系统项目实战(附源码+文档)