首先,看看老大给我的任务:实现一个模块间的内存管理库, 实现以下功能
遇到的问题:
1,进程间最好用的通信方式是共享内存,内存大且操作容易。
2,数据量不确定是写入时的文件大小不确定,那么怎么来回改变共享内存大小。(可变数组行不通)
3,多个进程读,多次创建挂载共享内存,销毁时会出现问题。
4,读写不同步,写完之后读不是想要的结果。
5,重复性的问题,避免重复读。
下面详细介绍我的痛苦历程:
首先,我们来说说共享内存,共享内存是进程间通信的一种很好用的方式,内存足够大,创建销毁简单,在前面已经介绍过了,关于创建的函数见链接 http://blog.csdn.net/agoni_xiao/article/details/77165428
接下来,处理文件大小不稳定的情况,用get_blocksize函数,根据文件大小改变块的大小及个数。
我本来想用可变数组后来发现每次都读不完整,是因为可变数组是从地址访问到地址,如果别的程序用到你的地址,就会出现错误。
然后,想使用缓冲区环形和整型,但如果这样每次都需要开辟的内存是把整个文件写入共享内存,而不是一部分一部分去写,如果写一部分,第一个模块读完并载入新的数据,第二个模块就会读不到之前的数据,或者读到部分数据,所以放弃缓冲区的想法。环形缓冲区和整型缓冲区知识http://www.cnblogs.com/zengzy/p/5139582.html
对于读写的同步,写在前,读在后,每个块都有一个状态标志block_status,为1时表示该块已写入完成可读,为2时表示已读过。当第一个模块读完第一个块之后,继续读第二个块,当读到第二个块的时候,把第一个块状态置为1,以便后面的模块读取。图见下:
解决共享内存多次释放问题,是通过共享内存结构体中,保存创建好的信息,在下一块链接时,读取并判断。
废话少说,直接上代码.
头文件shm.h:
#include
#include
#include
#include
#include
#ifndef _SHAREMRY_H_HEADER
#define _SHAREMRY_H_HEADER
#define SIZE 1024*1024
struct share_temp
{
int read_success;
int size;
int block_status[10];
int is_readed[10];
int is_empty;
char text[SIZE];
int shmid_line;
void *shm_line;
};
void* rmapi_create_sharememory();
//int get_blockcount(int size,int bsize);
int get_blocksize(int size);
void init_is_readed(struct share_temp **shared);
int rmapi_put_frame(void* memory, const char* data, unsigned int data_size);
int rmapi_get_frame(void* memory,char** data,unsigned int data_size);
void read_file(int size, struct share_temp **shared,char** filedata);
void rmapi_destroy_read_sharememory(void* memory);
void rmapi_destroy_write_sharememory(void* memory);
#endif
读模块readshm.cpp
#include
#include
#include"shm.h"
using namespace std;
class ReadBlock
{
public:
ReadBlock(){}
~ReadBlock(){}
void* creatershm()
{
shm_line = rmapi_create_sharememory();
return shm_line;
}
//void File_opt();
private:
//struct share_temp sw;
void* shm_line;
};
int main()
{
ReadBlock rb;
int size,shmid_line;
//char* fdata = (char*)malloc(size);
void* readshm = rb.creatershm();
struct share_temp *spq =(struct share_temp *)readshm;
size = spq->size;
char* fdata = (char*)malloc(size);
rmapi_get_frame(readshm, &fdata, size);
rmapi_destroy_write_sharememory(readshm);
}
写模块writeshm.cpp
#include
#include
#include"shm.h"
using namespace std;
void *rmapi_create_sharememory();
class WriteBlock
{
public:
WriteBlock(){}
~WriteBlock(){}
void *createwshm()
{
shm_line = rmapi_create_sharememory();
return shm_line;
}
private:
//struct share_temp sw;
void* shm_line;
};
int main(int argc,char *argv[])
{
WriteBlock wb;
int count,size,bsize,shmid_line;
FILE *fr;
fr = fopen(argv[1],"a+");
fseek(fr,0,SEEK_END);
size = ftell(fr);
rewind(fr);
void *wshmline = wb.createwshm();
struct share_temp* write_shm = (struct share_temp *)wshmline;
char* fdata = (char *)malloc(size);
fread(fdata,size,1,fr);
cout<<"the fread fileinfo is"<size = size;
cout<<"the wshmline->size:"<size<
方法库sharemrylib.cpp#include
#include
#include
#include
#include"shm.h"
using namespace std;
void init_is_readed(void **memory)
{
void *rst = *memory;
struct share_temp *shared = (struct share_temp *)rst;
int rf = 0;
for(rf;rf<10;rf++)
{
shared->is_readed[rf] = 0;
cout<<"init_is_readed"< 1024*1024)
{
bs = 1024*1024;
}
if(size > 1024*512 && size < 1024*1024)
{
bs = 1024*8;
}
if(size >1024 && size < 1024*512)
{
bs = 1024;
}
if(size < 1024)
{
bs = 1024;
}
return bs;
}
int get_blockcount(int size,int bsize)
{
int count = size/bsize;
cout<<"the block count is:"<text;
int bsize = get_blocksize(size);
cout<<"the bsize is "<block_status[di] > 0)
{
switch (pos->is_readed[di])
{
case 1:
sleep(5);
//cout<<"the "<is_readed[di] = 2;
pos->is_readed[di-1] = 1;
readp =readp + bsize;
di += 1;
break;
case 2:
cout<<"the"<is_readed[di] = 1;
di += 1;
}
}
else
{
cout<<"wait the "<block_status[di] == 1 && pos->is_readed[di] == 1)
{
cout<<"the remind info is"<is_readed[di] = 2;
memcpy(readdata,readp,remind);
}
pos = NULL;
readp = NULL;
readdata = NULL;
}
void* rmapi_create_sharememory()
{
void *shm = NULL;
int shmid = shmget((key_t)1342, SIZE, 0666|IPC_CREAT);
if(shmid == -1)
{
cout<<"shmid failed"<shmid_line = shmid;
shared->shm_line = shm;
//framecount = shmid;
cout<<"memory attach at "<<(int)shm<text;
int bsize,count;
int ri = 0;
if(data_size>1024)
{
bsize = get_blocksize(data_size);
count = data_size / bsize;
int remind = (data_size - count * bsize);
cout<<"the remind size is:"<is_empty = 1;
for(ri;riblock_status[ri] = 1;
post->is_readed[ri] = 1;
sleep(3);
dost = dost + bsize;
data = data + bsize;
//free(tpbuf);
}
memcpy(dost,data,remind);
cout<<"the remind info is "<block_status[ri] = 1;
post->is_readed[ri] = 1;
}
else
{
memcpy(dost,data,data_size);
post->block_status[ri] = 1;
}
post = NULL;
dost = NULL;
}
int rmapi_get_frame(void* memory, char** data, unsigned int data_size)
{
struct share_temp* shared = (struct share_temp*)memory;
struct share_temp *post = shared;
char* filedata = *data;
int running = 1;
while(running)
{
if(shared->is_empty == 0)
{
cout<<"have read nothing,the shm is empty"<shmid_line;
void *shm = shared->shm_line;
if(shmdt(shm) == -1)
{
cout<<"shmdt failed"<shmid_line;
void *shm = shared->shm_line;
if(shmdt(shm) == -1)
{
cout<<"shmdt failed"<
makefile文件:
CPP = g++
CPPFLAGS = -fpic
LIB = libsharemry.so
HPATH = /home/xudong/share_memory/
LIBPATH = /home/xudong/share_memory/
edit:sharemry.o libsharemry.so readshm.o writeshm.o readshm readshm2 writeshm
readshm:
$(CPP) -o readshm readshm.cpp -I $(HPATH) -L $(LIBPATH) -lsharemry
readshm2:
$(CPP) -o readshm2 readshm2.cpp -I $(HPATH) -L $(LIBPATH) -lsharemry
writeshm:
$(CPP) -o writeshm writeshm.cpp -I $(HPATH) -L $(LIBPATH) -lsharemry
libsharemry.so:
$(CPP) -shared -o $(LIB) sharemrylib.o
sharemry.o:
$(CPP) $(CPPFLAGS) -c sharemrylib.cpp