写时复制,读时加载
实现写时复制,读时加载,原理为,申请内存时,只给一段线性地址空间,并不分配物理内存,当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中的修饰符,并提供实际示例,…...
算法模拟类题目解析
前言:最近开始偏系统的从简单到难一步步刷算法题,先从模拟题开始,下边附带题目与连接,感兴趣可刷刷也可看看我的思路。 一.字符串展开 链接:https://ac.nowcoder.com/acm/problem/16644 来源:牛客网 题意…...
CLIP ViT-H-14多场景适配方案:教育题库图像索引、医疗报告配图推荐、设计素材库检索
CLIP ViT-H-14多场景适配方案:教育题库图像索引、医疗报告配图推荐、设计素材库检索 1. 项目概述 CLIP ViT-H-14图像编码服务是基于CLIP ViT-H-14(laion2B-s32B-b79K)模型的图像特征提取解决方案。这项服务通过RESTful API和Web界面两种方式,为不同行业…...
从BUUCTF的Hack World靶场,聊聊那些年我们踩过的SQL注入“异或”盲注坑
从BUUCTF的Hack World靶场,聊聊那些年我们踩过的SQL注入"异或"盲注坑 在CTF竞赛的Web安全赛道上,SQL注入始终是经久不衰的考点。当新手们刚掌握联合查询和报错注入时,往往会在一道名为Hack World的题目前栽跟头——这道来自CISCN2…...
HUNYUAN-MT 7B翻译终端Typora Markdown写作增强:实时双语文档创作
HUNYUAN-MT 7B翻译终端Typora Markdown写作增强:实时双语文档创作 1. 引言 如果你经常用Typora写技术博客或者项目文档,可能遇到过这样的场景:好不容易写完一篇内容详实的文章,想要分享给国际社区,却卡在了翻译上。手…...
避坑指南:在K210上跑人脸68关键点,这些细节让你的疲劳检测更准
K210人脸疲劳检测实战:68关键点调优与工程化避坑指南 当你在车载监控或工业安全场景部署基于K210的疲劳检测系统时,是否遇到过这些情况?明明按照开源代码跑通了68关键点检测,但实际场景中闭眼判断总是不准;白天阳光直射…...
COSL超声相控阵列的声场分布与聚焦深度仿真
cosmol超声相控阵列声场分布和聚焦深度仿真 (可根据需求修改)超声相控阵列这玩意儿在工业检测和医疗领域用得贼多,核心就是通过控制不同阵元的发射时序实现声波聚焦。今天咱们用COMSOL搞个简单的二维仿真,看看怎么让声场在特定深度…...
Cassandra在大数据图像存储中的应用探索
Cassandra在大数据图像存储中的应用探索关键词:Cassandra、大数据、图像存储、分布式系统、数据管理摘要:本文旨在深入探索Cassandra在大数据图像存储领域的应用。我们将先介绍Cassandra的基本概念和特点,再详细分析它与大数据图像存储的适配…...
Qt 5.14.2下MQTT开发全攻略:从源码编译到实战应用(附完整代码)
Qt 5.14.2下MQTT开发全流程实战指南 在物联网应用开发中,MQTT协议因其轻量级和高效性成为设备通信的首选方案。对于使用Qt框架的开发者而言,将MQTT集成到项目中可以构建出功能强大的跨平台物联网应用。本文将深入探讨在Windows平台上使用Qt 5.14.2进行MQ…...
云原生图书馆管理系统架构设计:基于SaaS的一站式解决方案与实战案例分析
某中学图书馆数字化改造实战:传统Excel管理迁移至云端系统,借还效率提升300%,系统响应时间降低至200ms以内一、背景:传统图书馆管理的痛点分析1.1 技术债务积累在数字化转型的过程中,许多中小型学校图书馆依然停留在传…...
别再死记硬背了!用Python可视化理解L-smooth函数与梯度Lipschitz连续
别再死记硬背了!用Python可视化理解L-smooth函数与梯度Lipschitz连续 第一次接触L-smooth这个概念时,我盯着数学公式看了整整一个下午——梯度Lipschitz连续、二次上界、等价性证明,每个词都认识,连起来却像天书。直到我用Python画…...
