您的位置:首页 > 编程语言 > C语言/C++

C/C++ 日常学习总结(第二十二篇)共享内存实现C++

2014-09-23 14:11 597 查看
大家都知道进程之间的通信可以使用共享内存,但是在具体代码中如何实现呢?下面就介绍下操作原理和我自己的实现代码。

在linux下使用的是shmget,shmat,shmdt等函数,所以在网上看到这类的,基本就是在介绍linux环境下的实现,windows下不适用,但可以看其原理。

0.传输数据的结构定义

struct Splayer
{
int numid;
int age;
char sex;
char name[128];
char ip[256];
int  port;
};


上面结构的定义较为简单,仅为了测试使用。

1.我们会创建两个程序,一个称之服务端,一个称之客户端。

服务端:(1.)创建共享内存区域 (2.)内存映射到当前进程 (3.)写入数据

客户端:(1.)打开共享内存区域 (2.)内存映射到当前进程 (4.)读出数据

2.服务端

void CMySharedServerDlg::MySharedMemory()
{
/*
struct Splayer { int numid; int age; char sex; char name[128]; char ip[256]; int port; };
*/
//1.创建共享内存区域
HANDLE hfile = ::CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,65536,"GameQueen");
if(NULL==hfile)
{
AfxMessageBox("创建失败!",MB_OK,0);
return;
}

//2.内存映射
PVOID pview = NULL;
pview = ::MapViewOfFile(hfile,FILE_MAP_ALL_ACCESS,0,0,1024);
if (NULL==pview)
{
AfxMessageBox("映射失败!",MB_OK,0);
return;
}

//char* pMessage = "皇后come from MySharedServerDlg!";//单独字符串也可传输

Splayer player;
player.numid = 6666;
player.age = 24;
player.sex = '1';
strcpy(player.name,"tangwei");
strcpy(player.ip,"192.168.1.102");
player.port = 8080;
DWORD dmessage = sizeof(Splayer);

memcpy_s(pview,1024,&player,dmessage);

}
上面是源码,简诉下过程:

(1)、创建一个特定大小的文件映射对象,名称为“GameQueen”,也可以宏来定义。

(2)、将这个对象的文件视图映射到进程的地址空间,然后向视图中写入数据/字符串。

(3)、函数参数分析 

// Create the file mapping object.
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,   // Use paging file - shared memory
NULL,                   // Default security attributes
PAGE_READWRITE,         // Allow read and write access
0,                      // High-order DWORD of file mapping max size
MAP_SIZE,               // Low-order DWORD of file mapping max size
FULL_MAP_NAME           // Name of the file mapping object
);


pView = MapViewOfFile(
hMapFile,               // Handle of the map object
FILE_MAP_ALL_ACCESS,    // Read and write access
0,                      // High-order DWORD of the file offset
VIEW_OFFSET,            // Low-order DWORD of the file offset
VIEW_SIZE               // The number of bytes to map to view
);


3.客户端

源码:

void CMyShareClientDlg::MySharedMemory()
{
HANDLE hfile = OpenFileMapping(FILE_MAP_READ,FALSE,"GameQueen");
if (NULL==hfile)
{
AfxMessageBox("不能打开共享内存",MB_OK,0);
return;
}
PVOID pview;
pview = ::MapViewOfFile(hfile,FILE_MAP_READ,0,0,1024);
if (NULL==pview)
{
AfxMessageBox("不能打开2",MB_OK,0);
return;
}
//char*  pStr = (char*)pview;
//CString str(pStr);
//OutputDebugString(str);
Splayer *player = (Splayer*)pview;//上面读取字符串,此处是读取结构体信息
}


过程分析:

(1.)执行客户程序CMyShareClientDlg

(2.)打开这个名称为“GameQueen”的文件映射对象

(3.)然后把相同的文件映射视图映射到自己的地址空间中

(4.)然后从视图中读取服务进程所写入的数据。

4.截图

服务端发送数据:



客户端接收数据:



5.注意

(1.)由于事件,信号,互斥对象和文件映射等这些内核对象都共享同一个名字空间,所以如果这个名字和其他一个对象的名称重名的话那么将创建失败。

(2.)为了实现共享内存,进程应首先调用CreateFileMapping函数然后在hFile参数中传入INVALID_HANDLE_VALUE宏来替代句柄。相应的文件映射对象会从系统的分页文件中获得一段内存。如果hFile参数的值是INVALID_HANDLE_VALUE,那么你在调用CreateFileMapping时必须给共享内存指定一个大小值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐