有时候一个游戏,像RPG这种的,经常在游戏过程中需要频繁存档,在性能不好的平台上容易出各种问题,比如游戏Crash,存档丢失等等,今天想到一个可选的解法,就是用MMAP。虽然我到现在也没有搞懂这个机制究竟是怎样让程序员得到了好处,但是,至少这是一个有可能解决问题的办法。
代码:
1 #include <sys/mman.h> 2 #include <fcntl.h> 3 #include <stdio.h> 4 #include <memory.h> 5 #include <unistd.h> 6 #include <stdlib.h> 7 #include <fstream> 8 9 using namespace std; 10 11 class Profile 12 { 13 // the data 14 public: 15 int val1; 16 int val2; 17 int val3; 18 19 public: 20 Profile() 21 { 22 // NOT to set the default value, seriously. 23 } 24 void* operator new(size_t size) 25 { 26 return OpenProfile(size); 27 } 28 void operator delete(void* p) 29 { 30 31 } 32 void UpdateProfile() 33 { 34 // Synchronize the content between memory and filesystem 35 printf("msync() ret: %d\n", msync(this, sizeof(Profile), MS_SYNC)); 36 } 37 void CloseProfile() 38 { 39 printf("munmap() ret: %d\n", munmap(this, sizeof(Profile))); 40 } 41 42 private: 43 static void* OpenProfile(size_t size) 44 { 45 void* ret = NULL; 46 // open the file which name is "Profile". 47 int fd = open("Profile", O_RDWR); 48 // if there is not this file yet, create it. 49 if(-1 == fd) 50 { 51 // Create the "Profile" file and write '00000..' in it, and the size of this file is sizeof(Profile). 52 ofstream outfile("Profile", ofstream::out | ofstream::trunc | ofstream::binary); 53 outfile.seekp(size - sizeof(char), ios::beg); 54 outfile << '\0'; 55 outfile.close(); 56 57 fd = open("Profile", O_RDWR); 58 if(-1 == fd) 59 { 60 printf("cannot open \"file\""); 61 exit(0); 62 } 63 } 64 // Map the file 65 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 66 if(MAP_FAILED == ret) 67 { 68 printf("cannot map file"); 69 exit(0); 70 } 71 72 return ret; 73 } 74 }; 75 76 int main() 77 { 78 // OPEN the Profile, and if there is no Profile now, will create one. 79 Profile* ptr = new Profile(); 80 81 // MODIFY the profile. 82 ptr->val1 = 10; 83 ptr->val2 = 20; 84 ptr->val3 = 30; 85 86 // This code SAVE 87 ptr->UpdateProfile(); 88 89 // This code CLOSE 90 ptr->CloseProfile(); 91 delete ptr; 92 93 // READ the Profile: 94 ptr = new Profile();//nothing else need to do, you could see the profile has already been read in. 95 printf("val1 = %d, val2 = %d, val3 = %d\n", ptr->val1, ptr->val2, ptr->val3); 96 97 return 0; 98 }
上面这个存档类Profile,使用方法变简单了,只要new出来,就相当于进行了read存档的操作。在需要存档的时候可调用UpdateProfile,但实际上,由于mmap的机制,即使你没有调用UpdateProfile,存档实际上也有可能是保存了的。
不过我只知道mmap是把文件映射到内存中,这样你读写内存的时候实际上相当于读写了文件。对于mmap的原理和得到的实惠还不知晓。