写时复制,读时加载
实现写时复制,读时加载,原理为,申请内存时,只给一段线性地址空间,并不分配物理内存,当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中的修饰符,并提供实际示例,…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...