主要涉及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](https://i-blog.csdnimg.cn/blog_migrate/982609fc798238551e388eb265afdfb6.jpeg)
![544e935182443bf95c794430aa75529e.png](https://i-blog.csdnimg.cn/blog_migrate/ece8cca40a22d110ffbb8dd620a360a8.jpeg)
![2d996dc29283757d00fd52e1207897c5.png](https://i-blog.csdnimg.cn/blog_migrate/80372f6a283f4bcbeb3db6041fde5ca6.jpeg)