32位系统使用文件作为媒介来模拟大于4G内存访问
代码一篇,暂时没发现bug:
1 // vm_mgr.cpp : Defines the exported functions for the DLL application. 2 // 3 4 #include "stdafx.h" 5 6 #include <Windows.h> 7 #include <vector> 8 #include <assert.h> 9 #include <tchar.h> 10 #include "../common/assist.h" 11 #include"../error_no/error_no.h" 12 #include "../Log/log.h" 13 #include "vm_mgr.h" 14 15 #define VM_ADDR_GEN(addr, index) (assert(index < 16), (((index & 0xfULL) << 60) | addr)) 16 #define VM_START_ADDR 0x100000000ULL 17 #define VM_WINDOW_SIZE (64 * 1024 * 1024UL) 18 #define VM_ALIGN_SIZE (64 * 1024) 19 20 struct vm_window { 21 void *p; 22 vm_ptr_t start; 23 unsigned long size; 24 }; 25 26 struct vm_item { 27 int addr_index; 28 HANDLE mutext; 29 HANDLE hMap; 30 vm_ptr_t vm_start_ptr; 31 unsigned long long vm_size; 32 struct vm_window window; 33 TCHAR file_path[MAX_PATH]; 34 }; 35 36 struct { 37 std::vector<struct vm_item> tbl; 38 } vm; 39 40 static int find_empty_index() 41 { 42 int addr_index; 43 int i; 44 45 for (addr_index = 0; ; addr_index++) { 46 for (i = 0; i < vm.tbl.size(); i++) { 47 if (vm.tbl.at(i).addr_index == addr_index) 48 break; 49 } 50 assert(addr_index <= 16); 51 if (i >= vm.tbl.size()) 52 return addr_index; 53 } 54 } 55 56 vm_ptr_t vm_alloc(unsigned long long size) 57 { 58 TCHAR tmp_path[MAX_PATH]; 59 TCHAR tmp_file_path[MAX_PATH]; 60 int err; 61 struct vm_item vm_item; 62 63 GetTempPath(ARRAY_SIZE(tmp_path), tmp_path); 64 GetTempFileName(tmp_path, _T("DediProg"), 0, tmp_file_path); 65 66 HANDLE hFile = CreateFile( 67 tmp_file_path, 68 GENERIC_READ | GENERIC_WRITE, 69 FILE_SHARE_READ | FILE_SHARE_WRITE, 70 NULL, 71 OPEN_ALWAYS, 72 FILE_FLAG_SEQUENTIAL_SCAN, 73 NULL 74 ); 75 if (hFile == NULL) { 76 return NULL; 77 } 78 79 vm_item.hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, size >> 32, size & 0xffffffff, NULL); 80 if (vm_item.hMap == NULL) { 81 err = GetLastError(); 82 return -E_ALLOC_MEMORY_FAIL; 83 } 84 vm_item.vm_start_ptr = (vm_ptr_t)MapViewOfFile( 85 vm_item.hMap, 86 FILE_MAP_ALL_ACCESS, 87 0 >> 32, 88 0 & 0xffffffff, 89 min(size, VM_WINDOW_SIZE) 90 ); 91 92 vm_item.addr_index = find_empty_index(); 93 vm_item.vm_start_ptr = VM_ADDR_GEN(vm_item.vm_start_ptr, vm_item.addr_index); 94 95 assert(vm_item.vm_start_ptr < ((-1) >> 4)); 96 97 CloseHandle(hFile); 98 hFile = NULL; 99 vm_item.vm_size = size; 100 vm_item.window.size = (unsigned long)min(VM_WINDOW_SIZE, size); 101 vm_item.window.start = vm_item.vm_start_ptr; 102 vm_item.window.p = (unsigned char *)vm_item.vm_start_ptr; 103 vm_item.mutext = CreateMutex(NULL, FALSE, NULL); 104 _tcsncpy(vm_item.file_path, tmp_file_path, ARRAY_SIZE(vm_item.file_path)); 105 vm.tbl.push_back(vm_item); 106 107 return vm_item.vm_start_ptr; 108 } 109 110 static __inline int in_region(vm_ptr_t ptr, unsigned long long size) 111 { 112 //static int dbg = 0; 113 int i; 114 115 for (i = 0; i < (int)vm.tbl.size(); i++) { 116 if ((ptr + size) <= (vm.tbl.at(i).vm_start_ptr + vm.tbl.at(i).vm_size) && (ptr >= vm.tbl.at(i).vm_start_ptr)) 117 return i; 118 //if (ptr + size > vm.tbl.at(i).vm_start_ptr + vm.tbl.at(i).vm_size) 119 // i = 'DEAD'; 120 //if (ptr < vm.tbl.at(i).vm_start_ptr) 121 // i = 'INVA'; 122 } 123 124 LOG_BEGIN { 125 log_add("----------------------------------------------"); 126 log_add("| Virtual Memory layout |"); 127 log_add("|--------------------------------------------|"); 128 for (i = 0; i < (int)vm.tbl.size(); i++) 129 log_add("|window.start_addr:%llx | window.size:%llx |", vm.tbl.at(i).window.start, vm.tbl.at(i).window.size); 130 log_add("|--------------------------------------------|"); 131 log_add("|user.ptr:%llx | user.size:%llx |", ptr, size); 132 log_add("----------------------------------------------"); 133 } LOG_END; 134 //dbg++; 135 assert(!"Invalid Memory"); 136 return -1; 137 } 138 139 static __inline unsigned char *scroll_window(int vm_index, vm_ptr_t ptr, unsigned long size) 140 { 141 unsigned char *p; 142 vm_ptr_t win_start; 143 unsigned long win_size; 144 unsigned long long file_offset; 145 unsigned long long tmp_offset; 146 147 148 win_start = vm.tbl.at(vm_index).window.start; 149 win_size = vm.tbl.at(vm_index).window.size; 150 151 152 UnmapViewOfFile(vm.tbl.at(vm_index).window.p); 153 154 win_size = (unsigned long)min(VM_WINDOW_SIZE, size); 155 156 assert(ptr >= vm.tbl.at(vm_index).vm_start_ptr); 157 file_offset = ptr - vm.tbl.at(vm_index).vm_start_ptr; 158 159 tmp_offset = file_offset / VM_ALIGN_SIZE * VM_ALIGN_SIZE; 160 tmp_offset = file_offset - tmp_offset; 161 162 file_offset = file_offset / VM_ALIGN_SIZE * VM_ALIGN_SIZE; 163 164 size += (unsigned long)tmp_offset; 165 166 p = (unsigned char *)MapViewOfFile( 167 vm.tbl.at(vm_index).hMap, 168 FILE_MAP_ALL_ACCESS, 169 file_offset >> 32, 170 file_offset & 0xffffffff, 171 size 172 ); 173 174 if (p) { 175 vm.tbl.at(vm_index).window.start = ptr; 176 vm.tbl.at(vm_index).window.size = size; 177 vm.tbl.at(vm_index).window.p = p; 178 179 return p + tmp_offset; 180 } 181 182 return NULL; 183 } 184 185 int vm_write(vm_ptr_t pointer, const unsigned char *buff, unsigned long long size) 186 { 187 int ret; 188 unsigned char *p; 189 unsigned long len; 190 int index = in_region(pointer, size); 191 192 ret = 0; 193 194 if (index == -1) { 195 ret = -1; 196 goto end; 197 } 198 WaitForSingleObject(vm.tbl.at(index).mutext, 20000); /* timeout 10s */ 199 while (size) { 200 len = (unsigned long)min(size, VM_WINDOW_SIZE); 201 p = scroll_window(index, pointer, len); 202 if (!p) { 203 ret = -1; 204 goto end; 205 } 206 207 memcpy(p, buff, len); 208 209 pointer += len; 210 buff += len; 211 size -= len; 212 } 213 end: 214 ReleaseMutex(vm.tbl.at(index).mutext); 215 return ret; 216 } 217 218 219 int vm_read(unsigned char *buff, vm_ptr_t ptr, unsigned long long size) 220 { 221 unsigned char *p; 222 unsigned long len; 223 int index; 224 225 assert(buff); 226 227 index = in_region(ptr, size); 228 229 if (index == -1) 230 return -E_ALLOC_MEMORY_FAIL; 231 232 while (size) { 233 len = (unsigned long)min(size, VM_WINDOW_SIZE); 234 p = scroll_window(index, ptr, len); 235 if (!p) 236 return -1; 237 238 memcpy(buff, p, len); 239 240 ptr += len; 241 buff += len; 242 size -= len; 243 } 244 245 return 0; 246 } 247 248 int vm_free(vm_ptr_t ptr) 249 { 250 int i; 251 252 LOG_BEGIN { 253 log_add("----------------------------------------------"); 254 log_add("| Virtual Memory layout |"); 255 log_add("|--------------------------------------------|"); 256 for (i = 0; i < (int)vm.tbl.size(); i++) 257 log_add("|window.start_addr:%llx | window.size:%llx |", vm.tbl.at(i).window.start, vm.tbl.at(i).window.size); 258 log_add("----------------------------------------------"); 259 } LOG_END; 260 261 for (i = 0; i < (int)vm.tbl.size(); i++) { 262 if (vm.tbl.at(i).vm_start_ptr == ptr) { 263 assert(vm.tbl.at(i).hMap); 264 265 UnmapViewOfFile(vm.tbl.at(i).window.p); 266 CloseHandle(vm.tbl.at(i).hMap); 267 268 DeleteFile(vm.tbl.at(i).file_path); 269 270 vm.tbl.erase(vm.tbl.begin() + i); 271 return 0; 272 } 273 } 274 275 assert(!"Invalid pointer"); 276 277 return 0; 278 }