c++ 共享内存_利用windows api共享内存通讯

主要涉及CreateFile,CreateFileMapping,GetLastError,MapViewOfFile,sprintf,OpenFileMapping,CreateProcess

CreateFile 获得文件Handle

CreateFileMapping创建Handle的映射

MapViewOfFile在进程的虚拟地址空间,部分的表示上面的映射(可以是一部分,最大是完全的映射,不会再大)

CreateProcess创建进程

参考:

百度百科的sprintf。MapOfview

CreateFile函数详解(确实很详细) - findumars - 博客园 CreateFileMapping

MapViewOfFile - 简书 Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收 - 啦啦风吹 - 博客园

C++从文件中读取整数输入数据 - charlsonzhao的博客 - CSDN博客

创建进程参考:CreateProcess()函数详解 - 夜空中最亮的星 - CSDN博客 windows下创建进程,CreateProcess()详解及用法 - System Architect - CSDN博客 CreateProcess()函数详解 - 夜空中最亮的星 - CSDN博客 CreateProcess示例 - Hisin Wang的专栏 - CSDN博客

主要内容:

使用Win32 API设计两个利用共享内存通信的程序。生产者进程生成Catalan序列,并写入内存共享对象。消费者进程从共享内存读取并输出序列。

生成的Catalan数的数目由命令行指定。

Catalan数的性质:

h(n)=h(n-1)*(4*n-2)/(n+1); h(n)=C(2n,n)/(n+1) (n=0,1,2,...) h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,...)

h(0)=1,h(1)=1 h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2)

简单的求法:若令f(2)=f(3)=1, 则f(n+1)=f(n)* (4*n-6)/n 。但是这里4*n-6/n会有除不尽。

可以catalan[i]*(4*j-6)/j

主要涉及CreateFile,CreateFileMapping,GetLastError,MapViewOfFile,sprintf,OpenFileMapping,CreateProcess函数。

函数的作用:

CreateFile 获得文件Handle

CreateFileMapping创建Handle的映射

MapViewOfFile在进程的虚拟地址空间,部分的表示上面的映射(可以是一部分,最大是完全的映射,不会再大)

CreateProcess创建进程。

各函数的参数及作用:

HANDLE CreateFile( LPCTSTR lpFileName, // 指向文件名的指针 DWORD dwDesiredAccess, // 访问模式(写 / 读) DWORD dwShareMode, // 共享模式 LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 指向安全属性的指针 DWORD dwCreationDisposition, // 如何创建 DWORD dwFlagsAndAttributes, // 文件属性 HANDLE hTemplateFile // 用于复制文件句柄 );

HANDLE WINAPI CreateFileMapping(

_In_ HANDLE hFile,

_In_opt_ LPSECURITY_ATTRIBUTES lpAttributes,

_In_ DWORD flProtect,

_In_ DWORD dwMaximumSizeHigh,

_In_ DWORD dwMaximumSizeLow,

_In_opt_ LPCTSTR lpName

);

HANDLE CreateFileMapping(

HANDLE hFile, //物理文件句柄

LPSECURITY_ATTRIBUTES lpAttributes, //安全设置

DWORD flProtect, //保护设置

DWORD dwMaximumSizeHigh, //高位文件大小(因为我们的游戏是32位的,所以此处设为 0)

DWORD dwMaximumSizeLow, //低位文件大小

LPCTSTR lpName //共享内存名称

);

BOOL CreateProcess(

 LPCTSTR lpApplicationName, // 应用程序名称

 LPTSTR lpCommandLine, // 命令行字符串

 LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程的安全属性

 LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性

 BOOL bInheritHandles, // 是否继承父进程的属性

 DWORD dwCreationFlags, // 创建标志

 LPVOID lpEnvironment, // 指向新的环境块的指针

 LPCTSTR lpCurrentDirectory, // 指向当前目录名的指针

 LPSTARTUPINFO lpStartupInfo, // 传递给新进程的信息

 LPPROCESS_INFORMATION lpProcessInformation // 新进程返回的信息

);

遇到的问题:

1. CreateFileMapping出错

解决:GetLastError获得错误信息,发现是文件大小的参数错误,不应该为0.调整后解决(书上0,0是因为如果已经存在文件,那么会映射真实大小)

2. 如何按输入到视图遇到了问题

解决:

for(int i=0;i<sizek;i++)

{

Int;

t=sprintf((char*)lpMapAddress+j,"%drn",catalan[i]); j+=t; }

3. 如何输出的问题

解决:直接采用printf %s输出

就是参考《操作系统概念第七版》P301的例子,写了两个程序。(虽然我觉得书上的确实有点问题,坑了我一个小时)

中间遇到的最大问题就是一开始忘了做错误检查,结果在CreateFileMapping就出错了,而我还傻乎乎的去找sprintf的问题,浪费了一个小时。

还有写输出程序的时候,有点想炫点c++ 的东西,结果turned out to be wasting time. 所以说编程的目的是解决问题,而不是秀自己。

还有体会深刻的一点:一定要仔细的分析函数的参数,弄清楚作用。比如CreateFileMapping中就有指定映像大小的参数,如果设为0就会导致问题(而且编译器不报错的)。(GetLastError 1006)

源码:

//catalan
#include<windows.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<iostream>
using namespace std;
#define MAX 20

int main(int argc,char*argv[]){

int sizek; vector<int>catalan; //这里用int,所以数据不能很大,不然会爆掉
catalan.push_back(1);     //第一个Catalan数为1
int temp=0;

if(argc!=2)
{
    fprintf(stderr,"argu wrong!n");
    return -1;
}
sizek=atoi(argv[1]);
if(sizek>MAX)
{
    fprintf(stderr,"size should be less than %dn",MAX);
    return -1;
}
if(sizek<1)
{
    fprintf(stderr,"size should be more than %dn",0);
    return -1;
}

for(int i=0;i<sizek-1;i++)
{
  int j=i+3;
  temp=catalan[i]*(4*j-6)/j;
  catalan.push_back(temp);
}

HANDLE hFile,hMapFile;
LPVOID lpMapAddress;

//handle
hFile=CreateFile("C:UserslenovoDesktopa.txt",
GENERIC_READ | GENERIC_WRITE,
0, //	要求独占对设备的访问。如果设备已经打开,CreateFile 调用会失败;如果成功地打开了设备,后续的 CreateFile 调用会失败
NULL, //指向一个 SECURITY_ATTRIBUTES 结构的指针,定义了文件的安全特性(如果操作系统支持的话)
OPEN_ALWAYS,  //告诉CreateFile打开一个已有的文件,如果文件存在,那么CreateFile会直接打开文件,如果不存在,则会创建一个新文件
FILE_ATTRIBUTE_NORMAL, //文件没有其他属性,比如隐藏
NULL); //用于复制文件句柄


if(hMapFile == NULL){
		cout << "wrong in CreateFile" << endl;
		return 0;
	}

//文件映射
hMapFile=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,1024*1024,TEXT("SharedObject"));  //0,0会报错;   书上0,0是因为如果已经存在文件,那么会映射真实大小
                                                                         //两个数字分别为文件高位大小,低位大小
int rst = GetLastError();                                                
    if (hMapFile == NULL || rst == ERROR_ALREADY_EXISTS)
    {
        cout<<rst<<endl;   //0,0 rst为1006 我tou
        printf("CreateFileMapping errorn");
        return 0;
    }

    //视图。视图可以是映射文件的一部分,也可以是全部
lpMapAddress=MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS, // 等价于CreateFileMapping的 FILE_MAP_WRITE|FILE_MAP_READ)
0,0,1024*1024);         //0,0表示文件映射起始偏移的高32位.低32位

if(lpMapAddress == NULL){
		cout << "wrong in MapViewOfFile" << endl;
		return 0;
	}

string s;
char a[20];
int j=0;
for(int i=0;i<sizek;i++)
{
int t=sprintf((char*)lpMapAddress+j,"%drn",catalan[i]);  //要转换  sprintf返回写入buffer 的字符数
j+=t;                                                      //注意rn  在MFC界面显示中要用“rn”。
}
//printf("%s",lpMapAddress);

STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

TCHAR szCommandLine[] = TEXT("C:UserslenovoDesktopsoncatalan.exe");

CreateProcess(NULL,           // No module name (use command line)
                  szCommandLine,  // Command line
                  NULL,           // Process handle not inheritable
                  NULL,           // Thread handle not inheritable
                  FALSE,          // Set handle inheritance to FALSE
                  0,              // No creation flags
                  NULL,           // Use parent's environment block
                  NULL,           // Use parent's starting directory
                  &si,            // Pointer to STARTUPINFO structure
                  &pi);            // Pointer to PROCESS_INFORMATION structure



Sleep(1000000);                       //S大写
UnmapViewOfFile(lpMapAddress);
CloseHandle(hFile);
CloseHandle(hMapFile);
return 0;
}

//soncatalan
#include<windows.h>
#include<cstdio>
#include<vector>
using namespace std;
#include<string>
#include<fstream>
#include<iostream>
#define MAX 20
#include<sstream>
int main(int argc,char* argv[]){

HANDLE hMapFile;
LPVOID lpMapAddress;

//文件映射
hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,false,TEXT("SharedObject"));

lpMapAddress=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,1024*1024);

/*ifstream data((char*)lpMapAddress);   //想多了直接试一下%s输出就挺好的。
        vector<int> res;
        string line;
        while(getline(data,line))
       {
        stringstream ss; //输入流
        ss << line; //向流中传值
        if (!ss.eof()) {
            int temp;
            while (ss >> temp) //提取int数据
                res.push_back(temp); //保存到vector
          }
       }
for(int i=0;i<res.size();i++)
{
    cout<<res[i]<<endl;
}*/
printf("%s",lpMapAddress);
cout<<"son finished!"<<endl;
Sleep(1000000);

UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
return 0;
}

效果:

c56827006dc16502ebd787d80e8bad75.png

544e935182443bf95c794430aa75529e.png

2d996dc29283757d00fd52e1207897c5.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值