进程《操作系统》第二版徐宗元第三章实验2

元心操作系统  时间:2021-04-11  阅读:()

3.7.2实验2  Windows 2000内存管理API函数的使用

一.实习要求

在Windows环境下模拟Windows2000的本地过程调用LPC通信方式之一 用内存映射文件(共享内存方式)实现cl ient/server架构进程间较大数据量的通信。

用VC编程创建一个server进程和一个cl ient进程 server进程用共享内存的名(lpName)调用CreateFi leMapping()函数产生并初始化共享内存 cl ient进程使用相同的共享内存的名来调用OpenFi leMapping()函数打开一个已命名的文件映射对象。 cl ient进程先向共享存储区写信息 server进程再从共享存储区读信息用信号量对象实现cl ient和server进程间的同步。

二.与实验相关的API介绍

1.Windows进程控制API函数---CreateProcess 函数

当一个线程调用CreateProcess时系统就会创建一个进程内核对象 为新进程创建一个虚拟地址空间并将可执行文件加载到该进程的地址空间中。然后系统再为新进程的主线程创建一个线程内核对象。通过执行启动代码该主线程便开始运行它最终调用WinMain、 wWinMain、main或wmain函数。如果系统成功地创建了新进程和主线程 该函数便返回TRUE。格式 BOOL CreateProcess(PCTSTR pszAppl iCationName,

PTSTR pszCommandLine,PSECURITY_ATTRIBUTES pSaProcess ,

PSECURITY_ATTRIBUTES psaThread ,BOOL bInheritHandles ,

DWORD fdwCreate,PVOID pvEnvironment ,PCTSTR pszCurDir ,PSTARTUPI NF0psiStartInfo,PPROCESS_I NFORMATION ppiProcInfo) ;

参数:pszAppicationName 参数用于设定新进程将要使用的可执行文件的名字该参数 99以上的情况是NULL。

PszCommandLine参数用于设定传递给新进程的命令行字符串 即想运行的可执行文件的名字。如它没有扩展名便假设它的扩展名为.exe 。psaProcess 、 psaThread参数分别设定进程对象和线程对象需要的安全性。如参数为

NULL系统为这些对象赋予默认安全性描述符。 也可以指定两个SECURITY_ATTRI BUTE结构并对它们进行初始化以便创建自己的安全性权限并将它们赋予进程对象和线程对象。bInheritHandles 进程对象和线程对象句柄的继承性fdwCreate 参数用于规定如何来创建新进程的标志。pvEnvironment 参数用于指向包含新进程将要使用的环境字符串的内存块。pszCurDir :参数允许父进程设置子进程的当前驱动器和目录如果本参数是 NULL则新进程的工作目录将与生成新进程的应用程序的目录相同。psiStartl nfo :参数用于指向一个STARTUPI NF结构。ppiProcI nfo :参数用于指向你必须指定的 PROCESS_INFORMATI结构。

2.由系统的页文件支持的内存映射文件实现进程间的数据通信的 API函数

(1)设定一块共享内存区域

先使用系统调用CreateFi leMapping为指定文件创建一个文件映射核心对象并指定共享内存区域的大小返回对象指针格式如下:

HANDLE CreateFi leMapping(HANDLE hFi le 

LPSECURITY_ATTRIBUTES lpFi leMappingAttributes ,DWORD flProtect 

DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow LPCTSTR lpName) ; 〃 hFi le 正常应是CreateFi le()传回来的一个有关文件的handle 用以告诉系统将它映射

到内存中。如果指定此参数为 INVALID_HANDLE_VALU E就可以使用页文件中的一块空间取代一般的文件。

〃 lpFi leMappingAttributes 安全属性指向文件映射内核对象的SECURITY_ATTRIBUTES结构的指针通常传递的值是 NULL。

.flProtect :文件的保护属性。可以是PAG E_READO NL或PAG E_READWRIT或PAG E_WRITECOP针对跨进程的共享内存应该指定此参数为 PAG E_READWRITE

.DwMaximumSizeHigh dwMaximumSizeLow映射之文件大小的高、低 32位。如果使用页面文件前参数值将总是为0。对于共享内存而言后参数值应该就是你要共享的内存大小。

.LpName共享内存的名。

返回值如果成功则函数传回一个 handle否则传回NULL如果参数中所指定的文件已经存在用GetLastError()会传回失败的理由ERROR_ALREADY_EXISTS

再用系统调用MapViewOfFi le把文件映射到本进程的地址空间 返回指向可用的内存映射地址空间的指针。格式如下

LPVOID MapViewOfFi le(HANDLE hFi leMappingObject , DWORD dwDesiredAccess ,

DWORD dwFi leOffsetHigh  DWORDdwFi leOffsetLow  DWORDdwNumberOfBytesToMap) ;

. hFi leMappingObject 文件映射核心对象的handle 这是CreateFi leMapping()或OpenFi leMapping()的返回值。

.dwDesiredAccess :对共享内存而言此值应该设为 FILE_MAP_ALL_ACCESS

〃 dwFi leOffsetHigh 、 dwFi leOffsetLow 映射文件的高、低32位偏移值。如果使用页面文件前参数应该总是为0。对于共享内存而言后参数应该总是0以便能够映射整个共享区域。

.dwNumberOfBytesToMap真正要被映射的字节数量。 如果指定为0,表示要映射整个空间。所以对共享内存而言最简单的做法就是将此参数指定为 0。

返回值如果成功,则传回一个指针,指向被映射出来的“视图”的起头。如果失败,传回

NULL。

(2)找出共享内存

如果共享内存要用于cl ient/server架构中,那么就只有server进程才应该以CreateFi leMapping()产生并初始化共享内存。所有的cl ient进程都应该使用相同的共享内存的名(lpName)来调用OpenFi leMapping()函数,打开一个已命名的文件映射对象,返回对象指针handle ,函数的格式如下HANDLE OpenFi leMapping(DWORD dwDesiredAccess ,

BOOL bInheritHandle , LPCTSTR lpName) .dwDesiredAccess :对于共享内存此值正常应该是 FILE_MAP_ALL_ACCESS

.BlnheritHandle :如果是TRUE表示这个handle可以被子进程继承。

. lpName共享内存的名。

返回值如果成功则函数传回一个 handie。如果失败则传回NULL。

第二个进程以及后续各进程在调用OpenFi leMapping()之后,应该调用MapViewOfFi le()以获得一个指针,指向共享内存。 它们调用函数后所获得的地址和第一个进程所获得的地址不相同。

(3)撤消映象关闭对象

一旦你完成了对共享内存的操作,你应该调用 UnmapViewOfFi le()用于设定原本由MapViewOfFi le()所返回区域的基地址然后再调用CloseHandle() 交出文件映射核心对象的handle 。

格式如下

BOOL UnmapViewOfFi le(LPCVOID lpBaseAddress);

〃 lpBaseAddress 指针指向共享内存。这个值必须符合 MapViewOfFi le()的传回值。返回值如果成功则传回TRUE如果失败则传回FALSE

BOOL CloseHandle(HANDLE hObject );

〃 hObject 打开对象的句柄。返回值如果函数调用成功返回值非零否则返回值是0。

(4) 共享存储区的应用例struct SharedBlock;extern SharedBlock*gpSharedBlock;struct SharedBlock

{short m_nStringCount;char_based(gpSharedBlock) *m_pStrings[1];

};

SharedBlock*gpSharedBlock;int main(int argc,char*argv[])

{

HANDLE hFi leMapping;hFi leMapping=CreateFi leMapping(INVALID_HANDLE_VALUE, //Fi le handle

NULL, // Security attributes

PAG E_READWRITE, //Protection

0, 102400, //Size-high 、 low 32bits

"ShareMem Data Block"); //NamegpSharedBlock=(SharedBlock*)MapViewOfFi le(hFi leMapping, //Fi le mapping Obiect

FILE_MAP_ALL_ACCESS, //Read/Write

0,0, //Offset-high 、 low 32 bits

0); //Map the whole thing

//读、写共享存储区……

UnmapViewOfFi le(gpSharedBlock);

CloseHandle(hFi leMapping);return(0);

}

三•与实验相关的编程 用指针_based指向共享内存

当完成文件到进程地址空间的映射后 就可利用首地址进行读写。 编译器用以解决一些与共享内存有关的问题是一个指针修饰词 称为_based ,允许指针被定义为从某一点开始起算的32位偏移值而不是内存中的绝对位置。下面程序有下语句char_based(gpSharedBlock) *m_pStrings[1];

变量m_pStrings是一个由"based”指针所组成的数组每一个指针指向 char 。虽然

它被定义为1个字节大这只不过是一种欺骗编译器的手法让它允许我们在这里先开辟出一个数组。虽然“ based”指针很好用你可能得在效率上付出一些代价。每次以“ based”指针处理数据CPU都必须为它加上基地址才能指向真正的位置。

四.cl ient/server进程间共享内存的进程通信程序参考源代码

(1)server进程程序

#include"windows.h"

# include<conio.h>

# include<stdl ib.h>

# include<fstream.h>

# include<io.h>

# include<string.h>

# include<stdio.h>struct SharedBlock;extern SharedBlock*gpSharedBlock;struct SharedBlock

{short m_nStringCount;char_based(gpSharedBlock) *m_pStrings[1]; };

SharedBlock*gpSharedBlock;////////////////////////////////////

//主函数int main(int argc,char*argv[])

{printf("共享存储区用于进程间的大数据量通信例\n");

HANDLE h_semaphore_ful l ; // 信号量对象句柄

DWORD wait_for_semaphore_ful l ;

HANDLE hFi leMapping; // 共享内存对象句柄hFi leMapping=CreateFi leMapping( // 创建共享内存对象

I NVALI D_HANDLE_VALUE,NULL, PAGE_READWRITE,0, 102400,

"ShareMem Data Block"); // 共享内存的名h_semaphore_ful l=CreateSemaphore(NULL,0, 16,"buffer_ful l");// 创建信号量对象STARTUPINFO si={sizeof(si) };PROCESS_INFORMATION pi ;

TCHAR szCommandLine[]=TEXT("com-c.exe");

CreateProcess(NULL, szCommandLine,NULL,NULL,

FALSE,0,NULL,NULL,&si ,&pi ) ; //gpSharedBlock创建cl ient进程

=(SharedBlock*)MapViewOfFi le( // 把文件映射到进程的地址空间hFi leMapping, FILE_MAP_ALL_ACCESS, 0,0,0);wait_for_semaphore_ful l=WaitForSingleObject(h_semaphore_ful l ,-1); //等待信号量对象char *str=gpSharedBlock->m_pStrings[0] ;printf("server process print%s\n",str);

UnmapViewOfFi le(gpSharedBlock);

CloseHandle(hFi leMapping);return(0);

}

(1)cl ient进程程序

#include"windows.h"

#include<conio.h>

#include<stdl ib.h>

#include<fstream.h>

#include<io.h>

#include<string.h>

#include<stdio.h>struct SharedBlock;extern SharedBlock*gpSharedBlock;struct SharedBlock

{short m_nStringCount;char_based(gpSharedBlock)

*m_pStrings[1]; };

SharedBlock*gpSharedBlock;

////////////////////////////////////

//主函数int main(int argc,char*argv[])

{

HANDLE h_semaphore_ful l ; //信号量对象句柄h_semaphore_ful l=OpenSemaphore( // 打开信号量对象

SEMAPHOREP_ALL_ACCESS, FALSE,"buffer_ful l");HANDLE hFi leMapping; //共享内存对象句柄hFi leMapping=OpenFi leMapping( // 打开共享内存对象

FILE_MAP_ALL_ACCESS,TRUE,

"ShareMem Data Block"); //gpSharedBlock=(SharedBlock*) 共享内存的名MapViewOfFi le(// 把文件映射到进程的地址空间hFi leMapping, FILE_MAP_ALL_ACCESS, 0,0,0);

DWORD dwMapErr=GetLastError(); if

(dwMapErr !=ERROR_ALREADY_EXISTS)gpSharedBlock->m_nStringCount= 1;char szLineBuffer[256];strcpy(szLi neBuffer, "客户发送到共享存储区的信息");int iLineCount=gpSharedBlock->m_nStringCount;char *pTextBuffer=(char *)gpSharedBlock+sizeof(SharedBlock)

+sizeof(char_based(gpSharedBlock) *) * (iLineCount-1);strcpy(pTextB uffer,szLi neB uffer);gpSharedBlock->m_pStrings[iLineCount-1]=

(char_based(gpSharedBlock) *)pTextBuffer;

pTextB uffer+=strlen(szLi ne B uffer)+1;long count;

ReleaseSemaphore(h_semaphore_ful l ,1,&count) ; //释放信号量对象

UnmapViewOfFi le(gpSharedBlock); //撤消映象CloseHandle(hFi leMapping);return 0;

}

五.示例程序的结果分析

本例中cl ient进程由server进程运行时创建无继承的子进程 server进程程序和cl ient进程程序分别编译、链接后生成com-r.exe和com-c.exe文件运行com-r.exe文件结果如下 共享存储区用于进程间的大数据量通信例server process print客户发送到共享存储区的信息

RepriseHosting:$27.97/月-L5640,16G内存,1TB硬盘,10TB月流量,西雅图机房

RepriseHosting是成立于2012年的国外主机商,提供独立服务器租用和VPS主机等产品,数据中心在美国西雅图和拉斯维加斯机房。商家提供的独立服务器以较低的价格为主,目前针对西雅图机房部分独立服务器提供的优惠仍然有效,除了价格折扣外,还免费升级内存和带宽,商家支持使用支付宝或者PayPal、信用卡等付款方式。配置一 $27.97/月CPU:Intel Xeon L5640内存:16GB(原...

香港云服务器最便宜价格是多少钱一个月、一年?

香港云服务器最便宜价格是多少钱一个月/一年?无论香港云服务器推出什么类型的配置和活动,价格都会一直吸引我们,那么就来说说香港最便宜的云服务器类型和香港最低的云服务器价格吧。香港云服务器最便宜最低价的价格是多少?香港云服务器只是服务器中最受欢迎的产品。香港云服务器有多种配置类型,如1核1G、2核2G、2核4G、8到16核32G等。这些配置可以满足大多数用户的需求,无论是电商站、视频还是游戏、小说等。...

华纳云CN2高防1810M带宽独享,三网直cn218元/月,2M带宽;独服/高防6折购

华纳云怎么样?华纳云是香港老牌的IDC服务商,成立于2015年,主要提供中国香港/美国节点的服务器及网络安全产品、比如,香港服务器、香港云服务器、香港高防服务器、香港高防IP、美国云服务器、机柜出租以及云虚拟主机等。以极速 BGP 冗余网络、CN2 GIA 回国专线以及多年技能经验,帮助全球数十万家企业实现业务转型攀升。华纳云针对618返场活动,华纳云推出一系列热销产品活动,香港云服务器低至3折,...

元心操作系统为你推荐
ASPSESSIONIDaspapple.com.cn苹果官网怎么序列号查询激活时间http404未找到HTTP 404 - 未找到文件,怎么解决啊asp.net网页制作使用ASP.net技术创建一个网页,如何做?期刊eset科创板首批名单科创板开市后,可以通过哪些基金参与科创板投资和打新股?瑞东集团福能集团是一个什么企业?站点管理有关站点的知识介绍?付款方式淘宝有哪几种付款方式?图文模块图文模块的标题栏填什么啊?
网站空间价格 个人域名注册 狗爹 themeforest directadmin 好看的桌面背景大图 网通代理服务器 hnyd qq数据库下载 太原联通测速平台 最好的免费空间 129邮箱 泉州移动 如何安装服务器系统 免费网页申请 四川电信商城 空间登陆首页 中国linux 好看的空间 magento主机 更多