事情的起源是这样的; 上周刚刚入职到一家新的公司, 在新公司中看了一周的代码。 其中有一个地方shmget了一块共享内存, 这块内存并不是用于实现进程间的通信,而是用来保留进程的关键数据。 当该业务进程跑飞了之后, 监控的watchdog会干掉该业务进程然后将其重新启动。 重新启动的进程便可以从保留内存中恢复数据。 老大布置了一个任务:将关键数据本地化, 这样不止是进程跑挂了, 就算down机了也能恢复之前的数据。

然后我就开始自己写代码模拟实现从文件中读出数据到一块大内存和将一块大内存写入到指定文件。 因为我对C的那写api不熟悉,就向着先用C++的fstream来实现。 一细想居然想不出一个一个能将文件直接读入一大片内存的函数。 默认情况下getline一次最多能将读入255个字符,而且貌似不会返回该次调用写读入了多少字符,而我的内存是一个数兆的字符数组, 好像getline不太能帮到我。 平时自己写些小打小闹的小程序没觉得什么, 真要解决一个实际问题时就拙计了。

然后开始借助万能的互联网,才发现一些fstream的一些我都没见过的API, 真是羞愧死。 具体而言就是fstream的rdbuf()方法没用过。filebuf这个类型没见过,更别提这个类型的pubseekoff和sgetn等。  如读入功能可以如下大致实现。

char* buf = new char[BUF_SIZE]; 
ifstream file("mem.buf",ios::binary); 
filebuf* pfbuf = file.rdbuf(); 
unsigned int size = pfbuf->pubseekoff (0,ios::end,ios::in); 
fbuf->sgetn(buf, size);




然后发现自己对linux的贡献内存的知识也记不清楚了。 于是翻出资料复习一下。 资料开宗明义的讲了linux下两种共享内存的挂接方法:1. 通过具名文件mmap到内存空间,可用于任意两个进程直接通信。 2. 匿名文件mmap到内存空间,常用于父子进程间通信。 忽然茅塞顿开, 第一种方式可以通过调用msync()函数来实现磁盘文件内容与共享内存区中的内容一致,即同步操作. 我们用的共享内存一定是具名的, 只需要调用一下这个接口不就天然解决了老大布置的人物了么??

但随即又产生了一个疑惑, 我们的代码是通过shmget创建的共享内存,它和通过mmap创建共享内存有什么区别和联系呢??还用什么别的方式创建共享内存呢?

抱着这个疑惑我又开始查资料。 首先创建共享内存的api有三个shm_open/shm_get/mmap. 得到了如下一些结果需要我去甄别,今天太晚了,留做明天作业。

1. posix共享内存shm_open 和 systemV共享内存shmget 方式。

2. shm_get实际上也会在/dev/shm产生一个临时的文件,所以实现原理上shm_get和mmap是一样的。只是mmap可以指定文件,down机后文件还在。而shm_get产生的是一个临时文件, 掉电后就不在了。

另外,自己需要再对c的一些文件操作的api和c++下面的一些文件操作的api有更深入的了解。