shmget 共享内存 同步读写文件一个进程写,多个进程读,读和写同步,边写边读

首先,看看老大给我的任务:实现一个模块间的内存管理库, 实现以下功能

1、该内存库通讯的数据量不确定, 最大5Mbit/s 
2、该内存库用于模块间的数据交互
3、该内存库只允许一个模块写入, 但可多个模块读取, 但需要各个读取模块没有任何相互干扰, 比如一个模块可能读取的速度较慢, 一个读取的速度较快
4、该内存库需要具有一定的数据缓冲, 实际的应用上, 用于视频帧数据的交互,  
5、封装成动态库
我拿到题目后,第一想法是,这很简单,两模块虽然不能同时写,同时读还是很容易的,接下来就傻了。。。老大要求的是实现同时读和写,并且多个读不影响。

遇到的问题:

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<stdlib.h>
#include<sys/shm.h>
#include<unistd.h>
#include<string.h>
#include<time.h>
#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<iostream>
#include<stdio.h>
#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<iostream>
#include<stdio.h>
#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"<<fdata<<endl;
	
//	rmapi_put_frame(wshmline, fdata, size);
	
	write_shm->size = size;
	cout<<"the wshmline->size:"<<write_shm->size<<endl;
	rmapi_put_frame(wshmline,fdata,size);
	rmapi_destroy_write_sharememory(wshmline);
	fclose(fr);
}
方法库sharemrylib.cpp
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#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"<<rf<<"is ok"<<endl;
	}
	shared = NULL;

}
int get_blocksize(int size)
{
	int bs;
	if(size > 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:"<<count<<endl;
	return count;
}
void read_file(int size, struct share_temp **shared,char** filedata)
{	
	char* readdata = *filedata;
	struct share_temp *pos;
	char *readp,*tpbuf;
	int count,remind;
	int di = 0;
	pos = *shared;
	readp = pos->text;
	int bsize = get_blocksize(size);
	cout<<"the bsize is "<<bsize<<endl;
	count = get_blockcount(size,bsize);
	cout<<"the count is"<<count<<endl;
	tpbuf = (char*)malloc(bsize);
	while(di <= count)
	{
		if(pos->block_status[di] > 0)
		{
			switch (pos->is_readed[di])
			{
				case 1:
					sleep(5);
					//cout<<"the  "<<di<<"  block text info is"<<readp<<endl;
					memcpy(tpbuf,readp,bsize);
                
					cout<<"the  "<<di<<"  block text info is"<<tpbuf<<endl;
					memcpy(readdata,tpbuf,bsize);
					memset(tpbuf,0,bsize);
					pos->is_readed[di] = 2;
					pos->is_readed[di-1] = 1;
					readp =readp + bsize;
					di += 1;
					break;
				case 2:
					cout<<"the"<<di<<"block is readed"<<endl;
					pos->is_readed[di] = 1;
					di += 1;
			}
		}
		else
		{
			cout<<"wait the "<<di<<"  write info"<<endl;
			di += 0;
		}
	}	
	cout<<"the di is "<<di<<endl;	
	if(pos->block_status[di] == 1 && pos->is_readed[di] == 1)
	{
		cout<<"the remind info is"<<readp<<endl;
		pos->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"<<endl;
	}
	shm = shmat(shmid, (void *)0, 0);
	struct share_temp *shared = (struct share_temp*)shm;
	shared->shmid_line = shmid;
	shared->shm_line = shm;
	//framecount = shmid; 
	cout<<"memory attach at "<<(int)shm<<endl;
	if(shm == (void*)-1)
	{
		cout<<"shmat failed"<<endl;
	}
	return shm;
}



int rmapi_put_frame(void* memory, const char* data, unsigned int data_size)
{
	
	struct share_temp* shared = (struct share_temp*)memory;
	
	struct share_temp *post = shared;
	char *dost = post->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:"<<remind<<endl;
	post->is_empty = 1;

	for(ri;ri<count;ri++)
	{
		cout<<"begin write the"<<ri<<"block"<<endl;
		
		memcpy(dost,data,bsize);
		cout<<"block"<<ri<<"the dost is"<<dost<<endl;
		
		post->block_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 "<<data<<endl;
	cout<<"the remind size is "<<remind<<endl;
	post->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"<<endl;
			sleep(5);
			continue;
		}
		read_file(data_size,&shared,&filedata);
		
		running = 0;
	}
}

void rmapi_destroy_read_sharememory(void* memory)
{
	struct share_temp* shared = (struct share_temp*)memory;
	int shmid = shared->shmid_line;
	void *shm = shared->shm_line;
	
	if(shmdt(shm) == -1)
	{
		cout<<"shmdt failed"<<endl;
		exit(EXIT_FAILURE);	
	}
	cout<<"shmdt success"<<endl;
	if(shmctl(shmid,IPC_RMID,0) == -1)	
	{			
		cout<<"shmctl failed"<<endl;
		exit(EXIT_FAILURE);	
	}
	cout<<"shmctl success"<<endl;
}
void rmapi_destroy_write_sharememory(void* memory)
{
	struct share_temp* shared = (struct share_temp*)memory;
	int shmid = shared->shmid_line;
	void *shm = shared->shm_line;
	
	if(shmdt(shm) == -1)
	{
		cout<<"shmdt failed"<<endl;
		exit(EXIT_FAILURE);	
	}
	cout<<"shmdt success"<<endl;
}

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

以上就是所有的源代码。




  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值