VC++中用内存映射文件

VC++中用内存映射文件
2000-01-30· 粟利民·电脑报

  在软件的开发过程中,有时需要控制一些程序使他们不能同时运行,也就是多个程序间互斥运行(还包括禁止同一程序运行多个实例)。针对这一问题,我们在Visual C++6.0中利用内存映射文件实现了多个程序间的互斥运行。内存映射文件可以创建一个没有和磁盘文件相联系的内存对象,将文件的信息映射到一个进程的地址空间上,我们可以访问该文件中的数据,就如同它位于内存中一样。同时,在程序设计中可以给内存映射文件对象起一个名字,这个名字在整个系统中是唯一的,这个名字可以在多个进程之间共享,通过名字共享能实现进行信息交换,进而实现多个程序间的互斥运行。

在讲述具体的编程方法之前,让我们先介绍和内存映射文件操作有关的几个重要的函

  1. CreateFileMapping的函数为指定的文件创建一个文件映射对象,该函数的原形如下:

    HANDLE CreateFileMapping(HANDLE hFile,//用于映射的文件句柄 LPSECURITY?ATTRIBUTES FileMappingAttributes,//内存映射文件的安全描述符 DWORD Flprotect,//文件映射对象的最大长度的高32位 DWORD dwMaximumSizelow,//最大长度的低32位 LPCTSTR IPNAME//指定这个内存映射文件的名字)

    值得注意的是,参数如果是OXFFFFFFFF,将在操作系统虚拟内存页面替换文件中创建文件映射对象,而不是使用磁盘文件,同时必须给出这个映射对象的大小。

  2. NAO VUEWIFFILE函数将文件的视图映射到一个进程地址空间上,返回LPVOID类型的内存指针。通过它,就可以直接访问文件视图中的信息。

LPVOID MAP VIEWLFFILE(HANDLE HFILEMAPPINGOBUCT,//映射文件对象句柄 DWORD DWDESIREDACCESS,//访问模式 DWORD DWFILEOFFSETHIGH,//文件偏移地址的高32位 DWORD DWFILEOFFSETHIGH,//文件偏移地址的低32位 DWORD DWNUMBEROFBYTESTOMAP//映射视图的大小)

在Visual c++6.0中我们用默认方式生成基于对话框的应用程序,在程序的初始化阶段,在CwinApp生类的Initln_stance函数的开始处,添加以下代码:

(//创建内存映射文件对象,mu_texRunning是其名字,所有需要互斥运行 //的程序都使用这个名字(这些代码对于需要互斥运行的程序是通用的)HANDLE hMap=CreateFileMapping((HANDLE)0Xffffffffnull,PAGE_READWRLTE,0,128,"Mu_texRunning") if(hMap==NULL)//如果创建失败 (AfxMessageBox("创建用于互斥运行的内存映文件对象失败!”,MB?OK MB??ICLNSTOP);

return FALSE;//退出此程序)

//如果已经存在这个同名对象,说明已有需要互斥的其他程序运行了

else if(GetLastError( )==ER_ROR_ALREADY_EXISTS)

(LPVOID ipMen=MapViewOFFile(hMap,FILE_MAP_WRITE,0,0,0);

Cstring str=(char*)ipMem;//获得已在运行的程序的描述信息

UnmapViewofFile(lpMem);//解除映射图

CloseHandle(hMap);//关闭此对象

AfxMessageBox(str,MB_ok MB_ICONSTOP);显示有关的描述信息

Return FALSE;//退出此程序)

Else//经过上面的检查,说明这是第一个运行的互斥程序

(LPVOID ip_mem=MapViewofFile(hMap,FILE_MAP_WRITE,0,0,0);

//这里可写入该程序运行的描述信息,上面的错误提示就是这信信息

strcpy((char*)lpMem,"xxx程序正在运行!”);

UnmapViewofFile(lpMem);//解除映射图)

//下面可以继续执行函数INITIN?STANCE原有的代码了

AfxEnableControl_comtainer();

//当程序运行结束了,要记住调用CHANDIE(HMAP)关闭这个对象句柄,//这里可以在Initinstance函数最后returnFALSE之前调用

CloseHandle(hMap);//关闭内存映文件对象句柄 RETURN false;)以上的程序在Visual C++6.中已调试通过。其他非对话框类型的程序可以在各自的初始化和终止阶段添加类似的代码,只是如果内存映射文件对象的句柄hMap可能在不同函数中使用,那就要将其定义成CwinApp生类的成员变量或是全局变量了。


以下是一个简单的 VC++6.0 MFC 应用程序,演示如何使用 MFC 实现串口通信: 1. 创建一个 MFC 对话框应用程序。 2. 在 CMyDialog 类的头文件中添加以下成员变量: ```c++ HANDLE m_hComm; OVERLAPPED m_osRead; OVERLAPPED m_osWrite; ``` 3. 在 OnInitDialog 函数中初始化串口: ```c++ CMyDialog::OnInitDialog() { CDialog::OnInitDialog(); // 初始化串口 m_hComm = CreateFile(_T("COM1"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (m_hComm == INVALID_HANDLE_VALUE) { MessageBox(_T("无法打开串口"), _T("错误"), MB_OK); return TRUE; } SetupComm(m_hComm, 1024, 1024); DCB dcb; GetCommState(m_hComm, &dcb); dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; SetCommState(m_hComm, &dcb); PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); // 初始化读写事件 m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); return TRUE; } ``` 4. 在 OnOK 函数中关闭串口: ```c++ CMyDialog::OnOK() { CloseHandle(m_osRead.hEvent); CloseHandle(m_osWrite.hEvent); CloseHandle(m_hComm); CDialog::OnOK(); } ``` 5. 实现一个函数来读取串口数据: ```c++ void CMyDialog::ReadFromPort() { char buf[1024]; DWORD dwRead; if (!ReadFile(m_hComm, buf, 1024, &dwRead, &m_osRead)) { if (GetLastError() != ERROR_IO_PENDING) { // 读取失败 return; } } WaitForSingleObject(m_osRead.hEvent, INFINITE); if (!GetOverlappedResult(m_hComm, &m_osRead, &dwRead, TRUE)) { // 获取结果失败 return; } // 处理读取到的数据 buf[dwRead] = '\0'; AfxMessageBox(buf); } ``` 6. 实现一个函数来写入串口数据: ```c++ void CMyDialog::WriteToPort(LPCTSTR lpBuf) { DWORD dwWritten; if (!WriteFile(m_hComm, lpBuf, _tcslen(lpBuf), &dwWritten, &m_osWrite)) { if (GetLastError() != ERROR_IO_PENDING) { // 写入失败 return; } } WaitForSingleObject(m_osWrite.hEvent, INFINITE); if (!GetOverlappedResult(m_hComm, &m_osWrite, &dwWritten, TRUE)) { // 获取结果失败 return; } // 写入成功 } ``` 7. 在需要读取或写入串口数据的地方调用上述函数即可。例如,在按钮点击事件中读取串口数据: ```c++ void CMyDialog::OnButtonRead() { ReadFromPort(); } ``` 注意,以上代码只是一个简单的示例,实际应用中还需要进行错误处理和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值