3.3 windows,ReactOS系统中页面的换出----1

[YIUI付费插件] 超级循环列表yiuisuperscroll 本文介绍基于YIUI框架实现循环列表(LoopListView2)的完整流程:在Scroll Rect上挂载LoopListView2并配置预制体,为Item添加Click同步事件;通过ServerListPanelComponent与ServerInfoItemComponent配合,使用YIUISuperScrollListRenderer和YIUISuperScrollListOnClick实现数据渲染与点击响应,支持动态刷新列表、选中状态管理及服务器信息绑定,高效构建可交互的滚动列表界面。 阅读详情

系列文章目录


3.3 页面的换出

在前一节中我们看到,如果有映射的页面已经被倒换到磁盘上即倒换文件中,那么对这个页面的访问就会引起一次缺页异常,而相应的异常处理程序就会从磁盘上把这个页面倒换进来。这自然就会产生一个问题:这个页面是在什么时候又是怎样跑到磁盘上去的呢?当然,页面(的内容)不会自己跑到磁盘上,而得有个行为主体将其倒出到磁盘上,这个行为主体就是内核线程MiBalancerThread() .

MiBalancerThread()


VOID STDCALL
MiBalancerThread(PVOID Unused)
{
   PVOID WaitObjects[2];
 ....

   WaitObjects[0] = &MiBalancerEvent;//通过Event唤醒
   WaitObjects[1] = &MiBalancerTimer;//通过定时器唤醒

   while (1)
   {
      Status = KeWaitForMultipleObjects(2,
                                        WaitObjects,
                                        WaitAny,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL,
                                        NULL);

      if (Status == STATUS_SUCCESS)
      {//因为事件而被(某个线程)唤醒
         /* MiBalancerEvent */
         CHECKPOINT;
         while (MmStats.NrFreePages < MiMinimumAvailablePages + 5)
         {//循环,知道有一个数量的空闲物理页面
            for (i = 0; i < MC_MAXIMUM; i++)
            {
               if (MiMemoryConsumers[i].Trim != NULL)
               {//调用内存消费者的修剪函数
                  NrFreedPages = 0;
                  Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);
                  if (!NT_SUCCESS(Status))
                  {
                     KEBUGCHECK(0);
                  }
               }
            }
         }
         InterlockedExchange(&MiBalancerWork, 0);
         CHECKPOINT;
      }
      else if (Status == STATUS_SUCCESS + 1)
      {
         /* MiBalancerTimer *///因超时而被唤醒
         ShouldRun = MmStats.NrFreePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;
         for (i = 0; i < MC_MAXIMUM; i++)//对于所有的内存消费者
         {
            if (MiMemoryConsumers[i].Trim != NULL)
            {
               NrPagesUsed = MiMemoryConsumers[i].PagesUsed;
               if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun)
               {//本消费者占用页面数已超过配额,或总库存已降到危险点
                  if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget)
                  {
                     Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,
                                   MiMinimumPagesPerRun);
                  }
                  else
                  {
                     Target = MiMinimumPagesPerRun;//每次至少修剪的数量
                  }
                  NrFreedPages = 0;
                  //执行本消费者的修剪函数
                  Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
                  if (!NT_SUCCESS(Status))
                  {
                     KEBUGCHECK(0);
                  }
               }
            }
         }
      }
      else
      {//因其他原因被唤醒,不应发生
         DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
         KEBUGCHECK(0);
      }
   }
}

这个线程平时都在睡眠,但是周期性地通过事件MiBalancerTimer 被定时器唤醒。此外,这个线程也可以通过事件 MiBalancerEvent 被唤醒,这发生在需要分配物理页面却发现库存不足的时候每当这个线程被唤醒的时候,它就借助若干个内存“消费者(Consumer)”的“修剪函数”对内存加以“修剪(Trim)”。所谓修剪,就是把一些判断为暂时不会被访问的页面(的内容)倒换出去,腾出所占据的物理页面另行分配,

如前所述,所谓内存“消费者”并不是指实际占用着物理页面的进程,而是指各种不同的用途例如用户空间的页面映射,内核中的可倒换物理页面池、不可倒换物理页面池,磁盘上扇区内容的高速缓存等。内核中有个结构数组MiMemoryConsumers[],其中的每个元素都代表一个“消费者”其下标可以是:

#define MC_CACHE                            (0)
#define MC_USER                             (1)
#define MC_PPOOL                            (2)
#define MC_NPPOOL                           (3)
#define MC_MAXIMUM                          (4)

显然,每一种用途即“消费者”都应该提供自己的修剪函数:但是目前ReactOS只为MC_CACHE和MC_USER提供了修剪函数。换言之,另两种用途的页面是不让修剪的。其中用户空间页面所映射物理页面的修剪函数为MmTrimUserMemory()。

MmTrimUserMemory()

[MiBalancerThread()>MmTrimUserMemory()]

/* FUNCTIONS *****************************************************************/

NTSTATUS
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
{
   PFN_TYPE CurrentPage;
   PFN_TYPE NextPage;
   NTSTATUS Status;

   (*NrFreedPages) = 0;

   CurrentPage = MmGetLRUFirstUserPage();//运用LRU算法找到第一个可以倒出的页面
   while (CurrentPage != 0 && Target > 0)
   {
      NextPage = MmGetLRUNextUserPage(CurrentPage);//下一个可以倒出的页面//倒出物理页面 CurrentPage


      Status = MmPageOutPhysicalAddress(CurrentPage);
      if (NT_SUCCESS(Status))
      {
         DPRINT("Succeeded\n");
         Target--;
         (*NrFreedPages)++;
      }
      else if (Status == STATUS_PAGEFILE_QUOTA)//已超过倒换文件的容量配额

      {
         MmSetLRULastPage(CurrentPage);//下次再来
      }

      CurrentPage = NextPage;
   }
   return(STATUS_SUCCESS);
}


参数Target是要求修剪的页面数量,NrFreedPages用来返回实际修剪的数量,另一个参数Priority实际上没有被用到。
修剪的对象是“最近最少被用到”的页面,相应的算法为LRU。与MiMemoryConsumers[]平行,内核中还有个队列头数组 UsedPageListHeads[],也是以 MC_USER 等为下标,凡是被分配用于某个消费者的物理页面,其数据结构都按LRU的次序挂在其队列中。LRU是一种常用的算法,我们就不深入到这里面去了。
找到修剪对象的物理页面号之后,就通过MmPageOutPhysicalAddressO)将其倒换出去。

MmPageOutVirtualMemory()

[MiBalancerThread()> MmTrimUserMemory() > MmPageOutPhysicalAddress()>MmPageOutVirtualMemory()]


NTSTATUS
NTAPI
MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
                       PMEMORY_AREA MemoryArea,
                       PVOID Address,
                       PMM_PAGEOP PageOp)
{
   PFN_TYPE Page;
   BOOLEAN WasDirty;
   SWAPENTRY SwapEntry;
   NTSTATUS Status;

   DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",
          Address, AddressSpace->Process->UniqueProcessId);

   /*
    * Check for paging out from a deleted virtual memory area.
    */
   if (MemoryArea->DeleteInProgress)
   {
      PageOp->Status = STATUS_UNSUCCESSFUL;
      KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
      MmReleasePageOp(PageOp);
      return(STATUS_UNSUCCESSFUL);
   }

   /*
    * Disable the virtual mapping.//关断目标页面的映射
    */
   MmDisableVirtualMapping(AddressSpace->Process, Address,
                           &WasDirty, &Page);

   if (Page == 0)
   {
      KEBUGCHECK(0);
   }

   /*
    * Paging out non-dirty data is easy.
    */
   if (!WasDirty)
   {//页面是干净的,物理页面空白或其内容与倒换文件中的对应页面完全相同
      MmLockAddressSpace(AddressSpace);
      MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, NULL, NULL);
      MmDeleteAllRmaps(Page, NULL, NULL);
      if ((SwapEntry = MmGetSavedSwapEntryPage(Page)) != 0)
      {
         MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry);
         MmSetSavedSwapEntryPage(Page, 0);
      }
      MmUnlockAddressSpace(AddressSpace);
      MmReleasePageMemoryConsumer(MC_USER, Page);
      PageOp->Status = STATUS_SUCCESS;
      KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
      MmReleasePageOp(PageOp);
      return(STATUS_SUCCESS);
   }

   /*
    * If necessary, allocate an entry in the paging file for this page
    */
   SwapEntry = MmGetSavedSwapEntryPage(Page);
   if (SwapEntry == 0)
   {
      SwapEntry = MmAllocSwapPage();
      if (SwapEntry == 0)
      {
         MmShowOutOfSpaceMessagePagingFile();
         MmEnableVirtualMapping(AddressSpace->Process, Address);
         PageOp->Status = STATUS_UNSUCCESSFUL;
         KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
         MmReleasePageOp(PageOp);
         return(STATUS_PAGEFILE_QUOTA);
      }
   }

   /*
    * Write the page to the pagefile
    */
   Status = MmWriteToSwapPage(SwapEntry, Page);
   if (!NT_SUCCESS(Status))
   {
      DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
              Status);
      MmEnableVirtualMapping(AddressSpace->Process, Address);
      PageOp->Status = STATUS_UNSUCCESSFUL;
      KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
      MmReleasePageOp(PageOp);
      return(STATUS_UNSUCCESSFUL);
   }

   /*
    * Otherwise we have succeeded, free the page
    */
   DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", Page << PAGE_SHIFT);
   MmLockAddressSpace(AddressSpace);
   MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, NULL, NULL);
   MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry);
   MmUnlockAddressSpace(AddressSpace);
   MmDeleteAllRmaps(Page, NULL, NULL);
   MmSetSavedSwapEntryPage(Page, 0);
   MmReleasePageMemoryConsumer(MC_USER, Page);
   PageOp->Status = STATUS_SUCCESS;
   KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
   MmReleasePageOp(PageOp);
   return(STATUS_SUCCESS);
}


需要倒换出去的页面可能是“干净”的,也可能是“脏”的。

所谓干净的页面,是指自从上一次建立通向这个物理页面的映射以来从未对其进行过写操作的面,具体有两种可能:

1,这是个刚被分配并建立映射但从未被写过的空白页面。这样的页面在倒换文件中尚无对应的倒换页面,也不需要有,因为以后需要时可以重新分配一个空白页面。所以只要删除其映射,并通过 MmDeleteAlRmaps()使其与所属的进程脱钩,最后释放这个物理页面就可以了

2,这是个从倒换文件换入的页面,但是换入之后从未被写过。这样的页面在倒换文件中已经有了对应的倒换页面,但是不需要改变倒换页面的内容。对于这样的页面,一方面要删除其映射,另一方面要使相应的页面映射表项指向倒换文件中的页面。凡是有了倒换页面的物理页面,其PHYSICAL PAGE结构中的SavedSwapEntry字段就指向这个倒换页面,现在一方面将该字段的内容转移到相应的页面映射表项中(并将其PAPRESENT标志位清0),另一方面通过 MmSetSavedSwapEntryPage()将这个字段清 0。然后再释放这个物理页面。

倒换页面是由“倒换页面项”SWAPENTRY描述的,这是个32位无符号整数,实际上是倒换文件号与文件内页面号的组合

所谓脏的页面,则是指自从上一次建立通向这个物理页面的映射以来已经对其进行过写操作的面,具体又有两种可能:

1,这本是个刚被分配并建立映射的空白页面,但是现在已经不再空白。这样的页面在倒换文件中尚无对应的倒换页面,但是需要有。所以通过MmAllocSwapPageO)分配一个倒换页面这个函数返回一个SWAPENTRY,说明是哪一个倒换文件中的哪一个页面。然后通过MmWriteToSwapPage()将页面的内容写入倒换文件,再将相应的页面映射表项改成指向倒换页面(并将其 PA_PRESENT标志位清0),最后释放该物理页面。

2,这是个从倒换文件换入的页面,但是换入之后已经被写过。这样的页面在倒换文件中已经有了对应的倒换页面,但需要改变其内容。所以也由MmWriteToSwapPageO)将页面的内容写入倒换文件,再将相应的页面映射表项改成指向倒换页面(并将其PA_PRESENT标志位清 0),最后释放该物理页面。

至于 MmWriteToSwapPage(),则已经属于文件操作的范畴,这里就不深入下去了。最后再概括一下倒换页面与物理内存页
面和页面映射表项PTE之间的关系:
1,如果(虚存)页面的内容在物理页面中,则相应的PTE指向该物理内存页面,而物理内存页面的 PHYSICAL_PAGE结构中的SavedSwapEntry 字段指向作为后备的倒换页面。
2,如果(虚存)页面的内容不在物理页面中,则相应的PTE直接指向倒换页面。

S7-1200 数据日志 数据日志文件按照标准 CSV 格式存储在 S7-1200 CPU 装载存储器或 S7-1200 SIMATIC 存储卡中。分别可通过 PLC Web 服务器或将数据文件传送到 PC 进行管理、查看。 一、测试目的: 下面以数据日志文件存储在 S7-1200 CPU 装载存储器中,使用PLC Web 服务器进行管理为例,实现下述功能: (1)执行“DataLogging”指令将产品型号“Type”,长度“Length”,宽度“Width”三个变量值写入到数据日志文件; (2)当写入的条数达到设定的3条 阅读详情

相关推荐

AI工程实战:如何在实际工程中运用Claude Code

本文探讨了利用大型语言模型(LLM)进行复杂工程项目的结构化工作流。核心策略包括:1)规划先行,通过"探索子代理任务"主动分析代码库并澄清需求;2)定制AI行为,要求简洁输出和列出未解决问题;3)将大型任务分解为多阶段计划以管理上下文窗口限制;4)利用GitHub Issues作为外部存储实现跨会话状态持久化。这种"规划-执行"模式将AI从代码生成器升级为项目管理代理,通过与GitHub CLI等工具深度集成,实现了高效的多阶段工程协作。该方法展示了AI辅助编程向流程

老孙 | Ethan Sun 的博客:AI 智能体与 AI 原生软件的工程实践 1094

深入理解Windows内存管理---2

内核对于物理页面的管理 物理页面在内核中的表示以及相关域的介绍 深入理解Windows内存管理—1 是对虚存地址的区间和区块的管理。 这些区块最终得要落实到物理内存才有实际的效用。 而物理内存的管理和使用是以页面为单位的,所以物理内存的管理实际上是对物理页面的管理。 内核中,物理页面是以数据结构PHYSICAL_PAGE代表的,类型定义如下: typedef struct _PHYSICAL_PA...

For Geek 609

FFmpeg + OBS 低延迟直播串流实战:从H264裸流到RTP组播的完整配置

本文详细介绍了如何利用FFmpeg将H264裸流转码为RTP协议,并通过组播技术实现与OBS客户端的超低延迟直播串流。文章深入剖析了FFmpeg关键参数调优、SDP文件生成与配置,以及OBS客户端的无缝拉流方法,为需要毫秒级实时交互的场景提供了一套去中心化、高效稳定的完整解决方案。

fanta的博客 830

Windows内存管理---5

页面异常 在为交割而分配一个区间时,区块的类型是MEM_COMMIT,此后这个区间就可以被访问了。但是,所谓“交割”也只是逻辑上的操作,并未落实到实际的物理页面的映射。于是,用户空间的程序在系统调用成功返回后就可能访问这个区间,然而一访问就因缺页异常而发生页面异常,因为此时实际上尚未建立起物理页面的映射。 发生页面异常时,内核走过类似于中断的过程,因异常的原因为页面异常而进入页面异常处理程序MmA...

For Geek 1178

2022-8-3----Android10.0(MTK)-----SN_Writer 写入 SN 注意事项

SN_Writer、写入SN

qq_854189624的博客 1万+

WRF-Chem新手避坑指南:从chem_opt到emiss_opt,那些手册里没明说的参数配置实战

本文为WRF-Chem新手提供从chem_opt到emiss_opt的参数配置实战指南,解析官方文档中未明确的常见陷阱与解决方案。通过华北重霾案例,详细讲解化学机制选择、排放源配置及特殊参数组合的注意事项,帮助用户避开常见错误,提升模拟效率。

weixin_30897079的博客 280

ReactOS内存管理机制:NT内存架构的精确复现

ReactOS作为一个开源的Windows NT兼容操作系统,其内存管理子系统完整复现了Windows NT内核的内存架构设计。通过深入分析ReactOS的源代码,我们可以清晰地看到Windows NT内存管理的核心机制和实现细节。 ### 内存管理架构概览 ReactOS的内存管理系统采用分层架构,主要包括以下几个核心组件: - **ARM3内存管理器**:ReactOS自主开发的新一代内...

gitblog_01008的博客 1038

<202505高项>《【VIP合集】 软考高项(第四版)十大知识域、五大过程组、ITTO输入输出工具、项目绩效域》

软考高项(第四版)十大知识域、五大过程组、ITTO输入输出工具、项目绩效域

Else 的博客 1854

3.3 windows,ReactOS系统中页面的换出----2,结构体PHYSICAL_PAGE

例如:第一章 Python 机器学习入门之pandas的使用。

zhyjhacker的博客 314

全面解读 SAP Business Data Cloud

SAP 在 2025 年初正式推出(简称BDC),它把、以及全新的统一封装为一项完全托管的 SaaS 服务,配套交付“语义层 + 数据产品 + 智能应用”三层能力,为企业构建真正贴近业务语境的 “Business Data Fabric”。这一方案不仅解决了跨系统数据碎片化、治理难及 AI 训练数据可信度低的问题,还为现有 BW 客户、S/4HANA以及第三方工作负载提供云上现代化路径和零拷贝数据共享机制。本文将围绕技术架构、核心组件、业务场景、迁移路线及未来展望展开,以 Henkel 等真实案例佐证。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 909

13、超声断层乳腺图像融合算法:乳腺癌诊断新突破

本文介绍了一种新型超声断层乳腺图像融合算法,通过结合超声透射(UTTc、UTTα)和反射断层图像(URT),实现对乳腺组织的多参数自动可视化。该算法能有效区分良性与恶性肿瘤,具有高准确性、无辐射、低成本等优势,适用于大规模乳腺癌早期筛查。初步临床测试验证了其可行性,未来有望成为乳腺癌诊断的新标准。

9q8w7e6r5的博客 155

Reactos 第 9 章 设备驱动 — 9.12 MDL

Windows NT MDL 机制解析 摘要: MDL(内存描述符列表)是 Windows NT 内核中连接虚拟地址与物理内存的关键数据结构,主要用于解决设备直接访问物理内存的问题。本文剖析了 MDL 的核心概念、生命周期和典型应用场景。 关键点: MDL 通过物理页数组(PFN)实现虚拟地址到物理地址的转换,支持 DMA 和直接 I/O 标准使用流程分为分配、锁定/填充、映射三个阶段 在 DIRECT_IO 模式下由 I/O 管理器自动管理,在 NEITHER 模式下需驱动自行处理 MDL 解决了用户缓冲

大坡3D软件开发 393

YOLOv11改进策略【卷积层】| ICCV-2023 引入Dynamic Snake Convolution动态蛇形卷积,改进C3k2

基于拓扑几何约束的动态蛇卷积用于管状结构分割DSConv(Dynamic Snake Convolution,动态蛇形卷积)模块的设计主要是为了更好地处理管状结构的分割任务,解决传统卷积在处理细管状结构时的不足。

Limiiiing的博客 1629

ReactOS 图形系统分析(23):引擎内存管理 — mem.c

位于(文件头自述 “GDI Driver Memory Management Functions”),实现 GDI 引擎的——既是引擎内部各模块的通用分配入口,也是 DDI 契约中(win32k.sys 导出)。是全引擎——全树 32 个文件、65 处调用(eng/ntgdi/字体驱动/显示驱动/DirectX 全在用),是《分析_4》2.x 各对象(SURFACE/EBRUSHOBJ/EXLATEOBJ 等)与《分析_18/19》等文件分配内存的共同底层。

大坡3D软件开发 74

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Windows内核情景分析 上 pdf

下载地址:网盘下载[图书简介]本书通过分析reactos的源代码介绍了windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有reactos的源代码(以及部分由微软公开的源代码)作为依据,使读者能深入理解windows内核的方方面面,也可以使读者的软件开发能力和水...

weixin_30765475的博客 640

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Windows内核情景分析 下 pdf

下载地址:网盘下载[图书简介]本书通过分析reactos的源代码介绍了windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有reactos的源代码(以及部分由微软公开的源代码)作为依据,使读者能深入理解windows内核的方方面面,也可以使读者的软件开发能力和水...

weixin_30642869的博客 641

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Windows 内存管理概念详解

本文详细讲解了 Windows 内核内存管理中的两个核心概念:虚拟地址描述符(VAD)和页帧号数据库(PFN Database)。VAD 是描述进程虚拟地址空间的 AVL 树节点,分为三种类型(SHORT/STANDARD/LONG),记录内存区域的属性、保护标志等信息。PFN Database 是管理物理页面元数据的数组,包含 MMPFN 结构体,跟踪每个物理页的状态、引用计数和映射关系。文章通过数据结构定义、操作流程和 ReactOS 源码对应关系,深入解析了这些关键机制的实现原理。

大坡3D软件开发 298

NTOSKRNL 内存管理器(MM)分析

ReactOS 内核内存管理器分析摘要(149字): ReactOS 内核内存管理器包含新旧两套子系统:旧版实现位于根目录,负责基础功能如VAD管理、缺页处理和页面文件;ARM3子系统作为当前主力,采用分层架构实现更完整的NT内存管理。ARM3包含初始化核心、物理内存管理(PFN、零页线程)、虚拟内存管理(VAD树、系统PTE)、页面错误处理、工作集管理以及池分配器等模块。两系统并存但功能逐渐向ARM3迁移,架构相关代码分离在不同子目录。内存管理器实现了从物理页分配到虚拟地址空间管理的完整功能链,支持Win

大坡3D软件开发 401

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

weixin_44218929的博客 197

工厂设备接MES为什么慢:协议识别与点表配置自动化的技术拆解

工业现场设备接 MES 的周期主要消耗在协议识别与点表配置。本文拆解这条链路的四层结构,给出点表映射的数据模型、两种部署架构的对比,以及可直接落地的三项验收口径与校验代码。适合工控集成、MES 实施、设备联网方向的工程师。

emfuture的博客 394

C# 数据结构和特殊类型

.NET Core(现称.NET)提供丰富数据结构,优化性能与开发效率。日常开发首选List<T>和Dictionary<TKey,TValue>;高性能场景推荐Span<T>与Memory<T>减少内存分配;并发环境使用ConcurrentDictionary等线程安全集合;避免非泛型集合如ArrayList。

cccloveforever的博客 689

list

的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。迭代到该位置,在这段位置上迭代需要线性的时间开销;最大的缺陷是不支持任意位置的随机访问,比如:要访问。还需要一些额外的空间,以保存每个节点的相关联信息。个元素,必须从已知的位置。

xie0510_的博客 274

向 excel、word、pdf 三种文档中占位符插入数据

【代码】向 excel、word、pdf 三种文档中占位符插入数据。

weixin_45934659的博客 61

软件商店常见问题标准处理流程

从底层软件源来看,/etc/apt/sources.list配置错误、源地址失效、公网与内网离线源混用、ARM64与x86_64架构源串用,以及DNS解析异常、系统代理配置错误,都会导致商店无法获取应用数据;打开该应用,确认可正常运行;软件商店作为系统内置的图形化软件分发与安装入口(UKUI桌面配套组件,底层依赖APT软件源),承担着应用软件的浏览、搜索、下载、安装、升级与卸载等核心功能,是终端软件部署与管理的关键通道。覆盖软件商店启动、页面加载、应用下载、安装、卸载、搜索、自身更新等全部业务场景。

qq_39496637的博客 282

【AI 开发从入门到进阶 · 10】收官篇:LoRA 微调、模型评估、推理加速与生产部署全链路

本文系统梳理了大模型微调与生产落地的全流程,从决策是否微调、优选LoRA技术方案,到代码实现、效果评估、推理加速与FastAPI服务封装,最终构建可迭代的生产级AI系统。强调“逐级升级”原则,倡导以数据闭环驱动优化,避免技术冲动。全系列贯穿工程化思维,提供可复用模板与实战建议,助力开发者从模型训练迈向稳定可用的AI服务部署。

信息安全领域优质创作者|操作系统领域专家 38

ARIA规范

ARIA用来补充原生HTML缺失的语义,原则:优先原生标签,ARIA仅做补充。 ARIA角色role:定义组件身份,分为地标角色、构件角色、文档角色;构件角色用于自定义弹窗、tab、下拉菜单等复杂组件; ARIA状态与属性:以aria-开头,描述组件实时状态;常用:aria-label、aria-labelledby、aria-describedby、aria-hidden、aria-expanded、aria-selected、aria-modal、aria-live; 常用场景:图标按钮用aria-l

2401_83227843的博客 419
上一篇: 3.2 页面异常-2
下一篇: 3.3 windows,ReactOS系统中页面的换出----2,结构体PHYSICAL_PAGE
zhyjhacker
博客等级 码龄17年 3203粉丝 406原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值