写时复制,读时加载
实现写时复制,读时加载,原理为,申请内存时,只给一段线性地址空间,并不分配物理内存,当cpu读、写该内存时,发生缺页中,或者写错误,中断处理程序根据前面设置的内容,决写分配物理内存,或者是共享内存,如果需要读取文件时,则根据需要读取相应的文件数据。
主要代码如下:
LPPE_FILE_ELEM load_pe_dll(char * lpFileName) {LPPE_FILE_ELEM lpSysFE, lpUserFE; //文件列表中的元素,保存文件信息//文件加载内存的默认地址//PIMAGE_DOS_HEADER pdh; //dos头PIMAGE_NT_HEADERS pnh; //pe文件头LPVOID pfile, pKrFile;PMEMORY_BASIC_INFORMATION pmbi;BYTE buf[512]; //临时块//补全文件目录路径add_patch((char *) buf, lpFileName);//1、从系统进程中查找是否已经加载lpSysFE = pe_find_file((char*) buf, get_sys_files_list());if (lpSysFE) {//系统中已经加载,进入下一步pKrFile = (LPVOID) lpSysFE->hModule;DbgPrint("dll已读入内存 : %s ,%x\n", lpSysFE->strFilePath,lpSysFE->dwNumberOfShares);//return lpFE->hModule;} else {//将文件加入系统文件列表中lpSysFE = kr_malloc(sizeof(PE_FILE_ELEM) + strlen((char*) buf) + 1);strcpy(lpSysFE->strFilePath, (char*) buf);if (load_file(lpSysFE->strFilePath, 0, 512, buf)) {//新exe头部的文件地址 指向PEpnh = (PIMAGE_NT_HEADERS) ((DWORD) buf+ ((PIMAGE_DOS_HEADER) buf)->e_lfanew);//系统进程中仅申请空间,读时加载pmbi = mem_virtual_alloc(&stMbiSys, 0,pnh->OptionalHeader.SizeOfImage, MEM_COMMIT,PAGE_READWRITE,MEM_IMAGE);pKrFile = (PBYTE) pmbi->BaseAddress;lpSysFE->hModule = (DWORD) pKrFile;lpSysFE->dwImgsize = pnh->OptionalHeader.SizeOfImage;lpSysFE->dwNumberOfShares = 0;list_push(get_sys_files_list(), (PLIST_ELEM) lpSysFE);load_pe_text((PIMAGE_DOS_HEADER) buf, (DWORD) lpSysFE->hModule,lpSysFE->strFilePath);if (!pKrFile) {//失败//DbgPrint("dll已读入内存 : %s ,%x\n");} else {//初始化时设置文件共享的次数为0,加入系统加载文件队列。}}} // if (lpFE)//2、检查用户空间 当前文件是否已经加载lpUserFE = pe_find_file(lpSysFE->strFilePath, get_current_file_list());if (lpUserFE) {//2、已经加载 直接返回return lpUserFE;} else {//第一次加入进程,将pKrfile的物理地址映射到 pfilepnh = (PIMAGE_NT_HEADERS) ((((PIMAGE_DOS_HEADER) pKrFile)->e_lfanew)+ (DWORD) pKrFile);pmbi = mem_virtual_alloc(MBI_USER_BASE, (LPVOID) pnh->OptionalHeader.ImageBase,pnh->OptionalHeader.SizeOfImage,MEM_COMMIT, PAGE_READWRITE, MEM_IMAGE);pfile = (PBYTE) pmbi->BaseAddress;DbgPrint("共享 dll: %s,%x,%x,%x,%x\n", lpSysFE->strFilePath, pfile,pKrFile, pnh->OptionalHeader.ImageBase);lpUserFE = kr_malloc(strlen((char*) lpSysFE->strFilePath) + sizeof(PE_FILE_ELEM)+ 1);strcpy(lpUserFE->strFilePath, lpSysFE->strFilePath);lpUserFE->hModule = (DWORD) pfile;lpUserFE->dwImgsize = lpSysFE->dwImgsize;lpUserFE->hSysModule = pKrFile;list_push(get_current_file_list(), (PLIST_ELEM) lpUserFE);lpSysFE->dwNumberOfShares++;DoRelocationTable(pfile);link_import(pfile);//文件头映射// mem_map_demand(pKrFile, pfile,// _ALIGN( pdh->e_lfanew + sizeof(IMAGE_NT_HEADERS32)// + pnh->FileHeader.NumberOfSections// * sizeof(IMAGE_SECTION_HEADER), 4096),// PG_USER_R_P);}return lpUserFE;
}
BOOL mem_fail_sys(DWORD code, DWORD addr) {DWORD temp;LPPE_FILE_ELEM fe;PMEMORY_BASIC_INFORMATION pmbi =mem_find_mbi(&stMbiSys,addr);//DbgPrint("内核%s错误 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",(code&2?"写":"读"), addr, code,// pmbi->BaseAddress, pmbi->RegionSize, pmbi->State, pmbi->Type);if (!pmbi) {return FALSE;}//如果是映射if (pmbi->State == MEM_COMMIT) {//分配物理内存,以4K为单位,if (pmbi->Type == MEM_IMAGE) {mem_physics(addr, 4096, PGE_SYS_RW_P);fe = (LPPE_FILE_ELEM) pe_find_from_addr(get_sys_files_list(), addr);if (fe->dwNumberOfShares != 0) {//直接分配内存,再读取文件//200对齐load_file_4k(fe, addr);} else {//正在读文件头}} else if (pmbi->Type == MEM_4MB_PAGES) {// MEM_4MB_PAGES://二级目录// DbgPrint("二级页表%x,%x\n", addr, (DWORD *) MiGetPteAddress(addr));mem_physics(addr, 4096, PG_USER_RW_P);//*(DWORD *) MiGetPteAddress(addr) =// get_freed_physics() + PG_USER_RW_P;} else {mem_physics(addr, 4096, PGE_SYS_RW_P);}//直接分配内存} //if (pmbi->State == MEM_COMMIT)else {return FALSE;}return TRUE;
}
BOOL mem_fail_user(DWORD code, DWORD addr) {DWORD temp;LPPE_FILE_ELEM fe;PMEMORY_BASIC_INFORMATION pmbi =mem_find_mbi(MBI_USER_BASE, addr);//DbgPrint("用户%s错误 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", (code&2?"写":"读"),addr, code,// pmbi->BaseAddress, pmbi->RegionSize, pmbi->State, pmbi->Type);if (!pmbi) {
//找不分配的段。return FALSE;}
//状态是不是已经提交
//只读,读写,还共享的读写
//如果是map类,分配内存,如果Image类,则读时加载,写时复制if (pmbi->State == MEM_COMMIT) {if (pmbi->Type == MEM_IMAGE) {fe = (LPPE_FILE_ELEM) pe_find_from_addr(get_current_file_list(),addr);if (fe->hSysModule == 0) {//说明是不是共享文件//DbgPrint("用户内存错误 0x%x , 0x%x , 0x%x , 0x%x \n", addr, code,// pmbi->BaseAddress, pmbi->State);mem_physics(addr, 4096, PG_USER_RW_P);load_file_4k(fe, addr);//break;} else {//DbgPrint("用户内存错误 %x,%x\n",addr,fe);//先读取系统内存,如果出错则会中断到mem_fail_sys,加载文件//如果是读取,则映射,如果是写则分配内存再复制if (code & 2) {//重新申请物理内,再复制//DbgPrint("用户写错误%x\n", addr);mem_physics(addr, 4096, PG_USER_RW_P);memcpy((PVOID) (addr & 0xFFFFF000),(PVOID) ((fe->hSysModule + (addr - fe->hModule))& 0xFFFFF000), 4096);} else {//DbgPrint("用户读错误%x\n", addr);//说明可能内核没有读取文件,也可能没有映射//先试读下,没有读取文件会中断后读取,再映射//mem_fail_sys(0,fe->hSysModule+addr-fe->hModule);temp = *(PDWORD) (fe->hSysModule + addr - fe->hModule);//函数自己内部齐,size=1~4096效果应是一样mem_map_demand(fe->hSysModule + addr - fe->hModule, addr,4096, PG_USER_R_P);}//直接分配内存,再读取文件//addr-pmbi->BaseAddressg}} else if ((pmbi->Type == MEM_PRIVATE)) {//if (pmbi->Type == MEM_IMAGE)mem_physics(addr, 4096, PG_USER_RW_P);}} // if (pmbi->State == MEM_COMMIT)else {return FALSE;}return TRUE;
}
相关文章:
写时复制,读时加载
实现写时复制,读时加载,原理为,申请内存时,只给一段线性地址空间,并不分配物理内存,当cpu读、写该内存时,发生缺页中,或者写错误,中断处理程序根据前面设置的内容&#x…...
Python和R基因组及蛋白质组学和代谢组学
🌵Python片段 1. 数据处理与清理 基因组病理学的数据通常非常庞大,且可能包括 DNA 或 RNA 测序结果、基因表达数据等。Python 提供了高效的数据处理工具。 工具和库 Pandas: 用于加载、清理和操作数据。Numpy: 用于高效的数值计算。Dask: 用于大规模数…...
selenium环境搭建详细过程
一、准备工作 在开始搭建 Selenium 环境之前,确保具备以下条件: 1.稳定的网络连接: 以便能够下载所需的软件和驱动程序。 2.操作系统基础: 对您的操作系统(如 Windows、Mac 或 Linux)有基本的了解和操…...

Linux知识 - VIM
VI于VIM linux系统里边内置了一个编辑器就叫做vi(visual editor),但vi的功能非常有限,所以一般Linux的使用人员会选择一个比vi更强大的编辑器vim Vim的三种工作模式 输入模式 在正常模式中按下别字母键,会进入插入模式…...

【数据结构】链表重难点突破
目录 一、链表的概念 二、链表的实现 2.1 链表的构建 2.2 从链表头部添加元素 2.3 从链表尾部添加元素 2.4 链表任意位置添加元素 2.5 常规方法实现 2.6 获取指定位置的元素 2.7 获取指定元素的位置 2.8 修改链表中某一节点 2.9 删除链表的头结点 2.10 删除链表的尾…...
大宗商品行业区块链应用
应用场景 区块链技术具有透明性、去中心化、不可篡改等特点,因此可以在大宗商品定价方面得到应用。通过区块链技术,相关交易的各方可以在无需依赖中心化第三方的情况下,实时、准确地获取定价信息。这种技术的应用能够提高效率、降低成本、提…...

Varjo:垂直起降机混合现实培训解决方案
混合电动垂直起降机(VTOL)作为一种新型的航空运输机具有超越传统汽车的安全性、与飞机相当的速度以及无与伦比的灵活起降功能。电动垂直起降机能够在建筑顶部、直升机场或是没有跑道的地区起飞或降落,且排放要远远低于由航空汽油驱动的传统飞…...
sqlite-vec一个SQLite3高效向量搜索扩展--JDBC环境使用
最近要用SQLite3,之前放出来了SQLiteUtile工具,方便操作。今天发现AIGC方面,RAG知识库需要使用向量数据库,来存储知识信息。一般呢都是用mysql,但无奈的是mysql就是不让用。突然又发现SQLite3有向量库扩展组件…...

10 基于深度学习的目标检测
首次完成时间:2024 年 11月 20 日 1. 使用OpenCV的dnn模块实现图像分类。 1)程序代码: import numpy as np import cv2# 解析标签文件 row open("model1/synset_words.txt").read().strip().split("\n") class_label …...

leetcode top100中的30道递归和贪心
21到30题,递归和贪心...

非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2
七、创建前端项目 你下载了nodejs吗?从cn官网下载:http://nodejs.cn/download/,或者从一个国外org网站下载,选择自己想要的版本https://nodejs.org/download/release/,双击下载好的安装文件,选择安装路径安…...
shell脚本(完)—脚本互调重定向的学习
免责声明 学习视频来自B 站up主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下代码、网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 脚本互调 在Shell脚本中&a…...
ant-design-vue中table某一列进行合并
ant-design-vue中table某一列进行合并 1、在colums中配置自定义渲染 {title: 区域,dataIndex: cityName,key: cityName,align: center,width: 120,customCell: (record, rowIndex, column) > {return {rowSpan: record.rowSpan}} },2、处理请求来的数据 tableData.dataSo…...

基于Springboot+Vue社区养老服务管理系统(源码+lw+讲解部署+PPT)
前言 详细视频演示 论文参考 系统介绍 系统概述 核心功能 用户角色与功能 具体实现截图 1. 服务信息查看功能 主要代码实现 截图: 2. 服务申请功能 主要代码实现 截图: 3. 公告信息查看功能 主要代码实现 截图: 4. 服务信息…...

大数据调度组件之Apache DolphinScheduler
Apache DolphinScheduler 是一个分布式易扩展的可视化 DAG 工作流任务调度系统。致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用。 主要特性 易于部署,提供四种部署方式,包括Standalone、Cluster、Docker和…...

介绍一下strlwr(arr);(c基础)
hi , I am 36 适合对象c语言初学者 strlwr(arr);函数是把arr数组变为小写字母 格式 #include<string.h> strlwr(arr); 返回值为arr 链接分享一下arr的意义(c基础)(必看)(牢记)-CSDN博客 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #incl…...
meterpreter常用命令 上
Meterpreter 是 Metasploit 框架中的一个高级 Payload,广泛用于渗透测试和攻击模拟。以下是一些常用的 Meterpreter 命令: 1. 基本命令 sysinfo 显示目标系统的基本信息(操作系统、架构等)。 getuid 获取当前用户的身份信息。…...
【kubernetes】kubernetes各组件的调用关系
目录 1. 说明2. Kubernetes组件概述2.1 控制平面组件2.2 节点组件 3. Kubernetes组件调用关系4. 示例说明 1. 说明 1.Kubernetes是一个开源的容器编排工具,其各个组件之间存在着复杂的调用关系,共同构建起一个完整的容器编排系统。2.Kubernetes集群主要…...

Java-08 深入浅出 MyBatis - 多对多模型 SqlMapConfig 与 Mapper 详细讲解测试
点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatisÿ…...
Vue.js修饰符
Vue.js 是一个渐进式JavaScript框架,用于构建用户界面。在Vue.js中,修饰符(Modifiers)是一种增强指令行为的工具,它们可以改变指令的默认行为。本文将详细讲解Vue.js中的修饰符,并提供实际示例,…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...