写时复制,读时加载

实现写时复制,读时加载,原理为,申请内存时,只给一段线性地址空间,并不分配物理内存,当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头部的文件地址 指向PE
			pnh = (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的物理地址映射到 pfile

		pnh = (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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/922516.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年wordpress、d-link等相关的多个cve漏洞poc

⚠️ 漏洞 ✅ CVE-2024-10914 在D-Link DNS-320、DNS-320LW、DNS-325和DNS-340L中发现的漏洞,版本直到20241028 GET /cgi-bin/account_mgr.cgi?cmdcgi_user_add&name%27;id;%27 HTTP/1.1✅ CVE-2024-11305 在Altenergy Power Control Software中发现的关键…

Spring框架特性及包下载(Java EE 学习笔记04)

1 Spring 5的新特性 Spring 5是Spring当前最新的版本,与历史版本对比,Spring 5对Spring核心框架进行了修订和更新,增加了很多新特性,如支持响应式编程等。 更新JDK基线 因为Spring 5代码库运行于JDK 8之上,所以Spri…

从搭建uni-app+vue3工程开始

技术栈 uni-app、vue3、typescript、vite、sass、uview-plus、pinia、axios 一、项目搭建 1、创建以 typescript 开发的工程 npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project2、安装sass npm install -D sass// 安装sass-loader,注意需要版本10&…

WPF中的登录界面

创建如下的目录结构&#xff1a; 2.在App.xaml.cs中设置为先登录验证之后再进入主页面 using Prism.Ioc; using System.Windows; using 校园访客系统.Views;namespace 校园访客系统 {/// <summary>/// Interaction logic for App.xaml/// </summary>public partia…

ros2学习日记_241124_ros相关链接

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

ETAS工具导入DBC生成Com协议栈

文章目录 前言DBC配置关键属性Cobra参数配置Cobra使用isolar工程配置总结前言 ETAS工具导入DBC主要也是生成arxml用的,ETAS推荐使用Cobra导入,本文介绍导入过程及注意事项 DBC配置关键属性 对于普通Com报文,配置为周期发送,及其周期,NmMessage配置为No,示例如下: 对…

Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化

Kafka&#xff1a;分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析&#xff1a;从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…

如果在docker 容器中安装ros遇到的问题

1.在容器内部无法修改时间&#xff0c;需要在宿主机外边修改时钟。修改时钟&#xff1a; hwclock --systohc或者执行 date -s "2024-11-24 19:25:10"2.容器内部内置有opencv4.5版本&#xff0c;需要卸载&#xff0c;重新安装4.2.0版本。记录折腾好久的卸载过程。 …

排序(Java数据结构)

1. 排序的概念及引用 1.1 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。(所有的排序都是默认从小到大排序) 稳定性&#xff1a;假定在待排序的记录序列中&#xff…

AutoDL安装docker问题

在AutoDL上租了卡&#xff0c;安装docker遇到一些问题&#xff1a; 1.执行 sudo docker run hello-world 报错 docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 解决方法 先查看docker有没有启动&#xff0c;…

ArcGIS定义投影与投影的区别(数据和底图不套合的原因和解决办法)

今天介绍一下ArcGIS中定义投影与投影的区别。 给大家解惑一下为什么经常出现自己的数据无法和底图套合的情况。 一 目录 1、ArcGIS定义投影与投影的概念区别 2、ArcGIS定义正确的坐标系 3、ArcGIS动态投影实现套合 4、ArcGIS地理坐标系转投影坐标系&#xff08;错误做法&am…

ChatGPT 桌面版发布了,如何安装?

本章教程教大家如何进行安装。 一、下载安装包 官网地址地址&#xff1a;https://openai.com/chatgpt/desktop/ 支持Windows和MacOS操作系统 二、安装步骤 Windows用户下载之后&#xff0c;会有一个exe安装包&#xff0c;点击运行安装即可。 注意事项&#xff0c;如果Windows操…

鸿蒙开发——根据背景图片来构建特定颜色的蒙版

效果图如下(文字部分马赛克处理)&#xff1a; 最近突然发现网易云和QQ音乐这些图片上方的蒙版颜色不是固定的&#xff0c;而是跟着图片内容走的&#xff0c;想看看能不能在鸿蒙实现&#xff0c;最后凭借俺寻思之力寻思出了一套流程(有bug&#xff0c;有时候蒙版直接透明了&…

clipboard

clipboard 现代复制到剪贴板。无闪光。只有 3kb 的 gzip 压缩。 安装 npm install clipboard --save第三方cdn提供商 <script src"https://cdn.jsdelivr.net/npm/clipboard2.0.11/dist/clipboard.min.js"></script>使用 data-clipboard-target"…

Matlab深度学习(四)——AlexNet卷积神经网络

网络搭建参考&#xff1a;手撕 CNN 经典网络之 AlexNet&#xff08;理论篇&#xff09;-CSDN博客 在实际工程应用中&#xff0c;构建并训练一个大规模的卷积神经网络是比较复杂的&#xff0c;需要大量的数据以及高性能的硬件。如果通过训练好的典型网络稍加改进&#xf…

《Python基础》之循环结构

目录 简介 一、for循环 1、基本语法与作用 2、使用 range() 函数配合 for 循环 3、嵌套的for循环 二、while循环 1、基本语法与作用 2、while 循环嵌套 &#xff08;1&#xff09;、while循环与while循环嵌套 &#xff08;2&#xff09;、while循环与for循环嵌套 简介 …

深入探索JMeter bin目录中的Properties文件:优化性能测试的关键

引言 在现代软件开发中&#xff0c;性能测试是确保应用质量和用户体验的重要环节。Apache JMeter作为一款流行的开源性能测试工具&#xff0c;提供了丰富的功能来模拟各种用户行为和负载情况。本文将深入探讨JMeter中的Properties&#xff08;属性&#xff09;功能&#xff0c…

第三十九篇 ShuffleNet V1、V2模型解析

摘要 ShuffleNet V1 ShuffleNet V1是由旷视科技&#xff08;Megvii&#xff0c;又称Face&#xff09;在2017年底提出的一种轻量级卷积神经网络架构。该网络专为移动设备和边缘计算环境设计&#xff0c;旨在以较低的计算资源实现高效的图像分类和其他计算机视觉任务。 特点与…

JavaScript练习——文本与图形

要求实现下面这个效果&#xff1a; 观察图片&#xff0c;我们的需求如下&#xff1a; 准备画布和上下文&#xff1a;在开始绘制之前&#xff0c;需要有一个HTML5 <canvas> 元素&#xff0c;并且获取其绘图上下文&#xff08;context&#xff09;&#xff0c;这是进行绘图…

[ubuntu]编译共享内存读取出现read.c:(.text+0x1a): undefined reference to `shm_open‘问题解决方案

问题log /tmp/ccByifPx.o: In function main: read.c:(.text0x1a): undefined reference to shm_open read.c:(.text0xd9): undefined reference to shm_unlink collect2: error: ld returned 1 exit status 程序代码 #include <stdio.h> #include <stdlib.h> #…