西电计算机操作系统进程通信.docx
- 文档编号:27258859
- 上传时间:2023-06-28
- 格式:DOCX
- 页数:23
- 大小:45.13KB
西电计算机操作系统进程通信.docx
《西电计算机操作系统进程通信.docx》由会员分享,可在线阅读,更多相关《西电计算机操作系统进程通信.docx(23页珍藏版)》请在冰豆网上搜索。
西电计算机操作系统进程通信
西安电子科技大学
计算机学院
实
验
报
告
题目:
进程通信
班级:
姓名:
学号:
内容摘要:
通信进程个数
2个
采用的通信方式
匿名管道
实验内容补充说明
无
一、分析和设计
1.理论分析
匿名管道主要用在本地父子进程之间的通信,首先由父进程创建一个匿名管道,在创建成功后,便可以获得匿名管道的读写句柄,然后父进程就可以向匿名管道中写入和读取数据。
要实现父子间通信,就要父进程中创建一个子进程,子进程可以继承和使用父进程的一些句柄。
在创建子进程的过程中,必须将子进程的标准输入句柄设置为父进程的读管道的句柄,子进程的标准输出句柄设置为父进程的写管道的句柄,这样,父子进程之间就可以通信了。
2.总体设计
管道一
先由父进程创建一个匿名管道,再由父进程获得读写句柄,构建读写的方式;由父进程创建子进程,实现父进程一样的通信功能。
管道二
二、详细实现
1、父进程的实现
1)消息以及成员函数和成员变量的声明
public:
afx_msgvoidOnBnClickedBtnCreatePipe();//创建匿名管道
afx_msgvoidOnBnClickedBtnWritePipe();//写匿名管道
afx_msgvoidOnBnClickedBtnReadPipe();//读匿名管道
voidParentReadPipe(void);//定义父进程读匿名管道的成员函数
voidParentWritePipe(void);//定义父进程写匿名管道的成员函数
voidCreateSecurityAttributes(PSECURITY_ATTRIBUTESpSa);//创建SECURITY_ATTRIBUTES结构的成员函数
voidCreateStartUpInfo(LPSTARTUPINFOlpStartUpInfo);//创建STARTUPINFO结构的成员函数
voidCreateNoNamedPipe(void);//创建匿名管道的成员函数
//分别代表要从匿名管道中读的数据和要写到匿名管道中的数据
CStringm_CStrReadPipe;
CStringm_CStrWritePipe;
//保存创建匿名管道后所得到的对匿名管道的读写句柄
HANDLEhPipeRead;
HANDLEhPipeWrite;
//保证匿名管道只创建一次
BOOLm_PipeIsCreated;
2)消息处理函数
//创建匿名管道按钮的消息处理函数
voidCNoNamedPipeParentDlg:
:
OnBnClickedBtnCreatePipe()
{
if(m_PipeIsCreated==FALSE)
{
this->CreateNoNamedPipe();
}
}
//写入数据到匿名管道中按钮的消息处理函数
voidCNoNamedPipeParentDlg:
:
OnBnClickedBtnWritePipe()
{
this->ParentWritePipe();
}
//从匿名管道中读取数据按钮的消息处理函数
voidCNoNamedPipeParentDlg:
:
OnBnClickedBtnReadPipe()
{
this->ParentReadPipe();
}
//接收数据
voidCNoNamedPipeParentDlg:
:
ParentReadPipe(void);
//发送数据
voidCNoNamedPipeParentDlg:
:
ParentWritePipe(void)
//创建SECURITY_ATTRIBUTES结构
voidCNoNamedPipeParentDlg:
:
CreateSecurityAttributes(PSECURITY_ATTRIBUTESpSa)
{
//这里必须将bInheritHandle设置为TRUE,
//从而使得子进程可以继承父进程创建的匿名管道的句柄
pSa->bInheritHandle=TRUE;
pSa->lpSecurityDescriptor=NULL;
pSa->nLength=sizeof(SECURITY_ATTRIBUTES);
}
//用来初始化新进程的STARTUPINFO成员
voidCNoNamedPipeParentDlg:
:
CreateStartUpInfo(LPSTARTUPINFOlpStartUpInfo)
//创建匿名管道
voidCNoNamedPipeParentDlg:
:
CreateNoNamedPipe(void);
2、子进程的实现
1)消息以及成员函数和成员变量的声明:
protected:
HICONm_hIcon;
//生成的消息映射函数
virtualBOOLOnInitDialog();
afx_msgvoidOnPaint();
afx_msgHCURSOROnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msgvoidOnBnClickedBtnWritePipe();
afx_msgvoidOnBnClickedBtnReadPipe();
//保存从父进程得到针对于匿名管道的读写句柄
HANDLEhPipeRead;
HANDLEhPipeWrite;
//分别代表要从匿名管道中读的数据和要写到匿名管道中的数据
CStringm_CStrWritePipe;
CStringm_CStrReadPipe;
//子进程读取匿名管道
voidChildReadPipe(void);
//子进程写匿名管道
voidChildWritePipe(void);
//子进程获取从父进程处继承得到的关于匿名管道的读写句柄
voidGetReadWriteHandleFromParent(void);
//只需要获取一次匿名管道的读写句柄即可
BOOLm_IsGettedParentHandle;
2)消息处理函数
//往匿名管道中写入数据按钮的消息处理函数
voidCNoNamedPipeChildDlg:
:
OnBnClickedBtnWritePipe()
{
//如果子进程还没有获得对匿名管道的读写句柄的话需要先获取句柄
this->GetReadWriteHandleFromParent();
ChildWritePipe();
}
//从匿名管道中读取数据按钮的消息处理函数
voidCNoNamedPipeChildDlg:
:
OnBnClickedBtnReadPipe()
{
//如果子进程还没有获得对匿名管道的读写句柄的话需要先获取句柄
this->GetReadWriteHandleFromParent();
ChildReadPipe();
}
//从匿名管道读取数据成员函数
voidCNoNamedPipeChildDlg:
:
ChildReadPipe(void);
//往匿名管道中写入数据
voidCNoNamedPipeChildDlg:
:
ChildWritePipe(void)
//需要获取继承自父进程的匿名管道读写句柄
voidCNoNamedPipeChildDlg:
:
GetReadWriteHandleFromParent(void)
{
if(this->m_IsGettedParentHandle==FALSE)
{
hPipeRead=GetStdHandle(STD_INPUT_HANDLE);
hPipeWrite=GetStdHandle(STD_OUTPUT_HANDLE);
this->m_IsGettedParentHandle=TRUE;
}
}
三、实验结果
启动父进程可执行文件,并单击创建匿名管道按钮,此时会弹出子进程窗口(新建了进程):
再在父进程的左边文本框中输入数据,单击写入数据按钮:
再在子进程窗口中单击读取数据按钮
四、心得体会
通过本次试验,更深入的了解了进程间通信中使用管道通信的方法,这种方法只能在父子进程之间通信,不能使用在其他地方,但在本地通信之间效率很高。
六、附录
1、父进程
public:
//创建匿名管道
afx_msgvoidOnBnClickedBtnCreatePipe();
//写匿名管道
afx_msgvoidOnBnClickedBtnWritePipe();
//读匿名管道
afx_msgvoidOnBnClickedBtnReadPipe();
//定义父进程读匿名管道的成员函数
voidParentReadPipe(void);
//定义父进程写匿名管道的成员函数
voidParentWritePipe(void);
//创建SECURITY_ATTRIBUTES结构的成员函数
voidCreateSecurityAttributes(PSECURITY_ATTRIBUTESpSa);
//创建STARTUPINFO结构的成员函数
voidCreateStartUpInfo(LPSTARTUPINFOlpStartUpInfo);
//创建匿名管道的成员函数
voidCreateNoNamedPipe(void);
//分别代表要从匿名管道中读的数据和要写到匿名管道中的数据
CStringm_CStrReadPipe;
CStringm_CStrWritePipe;
//保存创建匿名管道后所得到的对匿名管道的读写句柄
HANDLEhPipeRead;
HANDLEhPipeWrite;
//保证匿名管道只创建一次
BOOLm_PipeIsCreated;
constintdataLength=100;
CNoNamedPipeParentDlg:
:
CNoNamedPipeParentDlg(CWnd*pParent/*=NULL*/)
:
CDialogEx(CNoNamedPipeParentDlg:
:
IDD,pParent)
m_CStrReadPipe(_T(""))
{
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_PipeIsCreated=FALSE;
}
voidCNoNamedPipeParentDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialogEx:
:
DoDataExchange(pDX);
DDX_Text(pDX,IDC_EDIT_WRITE_PIPE,m_CStrWritePipe);
DDX_Text(pDX,IDC_EDIT_READ_PIPE,m_CStrReadPipe);
}
BEGIN_MESSAGE_MAP(CNoNamedPipeParentDlg,CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_CREATE_PIPE,
&CNoNamedPipeParentDlg:
:
OnBnClickedBtnCreatePipe)
ON_BN_CLICKED(IDC_BTN_WRITE_PIPE,
&CNoNamedPipeParentDlg:
:
OnBnClickedBtnWritePipe)
ON_BN_CLICKED(IDC_BTN_READ_PIPE,
&CNoNamedPipeParentDlg:
:
OnBnClickedBtnReadPipe)
END_MESSAGE_MAP()
//创建匿名管道按钮的消息处理函数
voidCNoNamedPipeParentDlg:
:
OnBnClickedBtnCreatePipe()
{
if(m_PipeIsCreated==FALSE)
{
this->CreateNoNamedPipe();
}
}
//写入数据到匿名管道中按钮的消息处理函数
voidCNoNamedPipeParentDlg:
:
OnBnClickedBtnWritePipe()
{
this->ParentWritePipe();
}
//从匿名管道中读取数据按钮的消息处理函数
voidCNoNamedPipeParentDlg:
:
OnBnClickedBtnReadPipe()
{
this->ParentReadPipe();
}
//接收数据
voidCNoNamedPipeParentDlg:
:
ParentReadPipe(void)
{
DWORDdwRead;
char*pReadBuf;
CStringcStrRecvData;
pReadBuf=newchar[dataLength];
memset(pReadBuf,0,dataLength);
if(!
ReadFile(hPipeRead,pReadBuf,dataLength,&dwRead,NULL))
{
MessageBox(TEXT("从匿名管道接收数据失败..."),
TEXT("提示"),MB_ICONERROR);
return;
}
cStrRecvData="从匿名管道接收数据成功:
";
cStrRecvData+=pReadBuf;
this->m_CStrReadPipe.Empty();
this->m_CStrReadPipe=pReadBuf;
UpdateData(FALSE);
MessageBox(cStrRecvData,TEXT("提示"),MB_ICONINFORMATION);
}
//发送数据
voidCNoNamedPipeParentDlg:
:
ParentWritePipe(void)
{
UpdateData();
if(!
this->m_CStrWritePipe.IsEmpty())
{
char*pSendData;
DWORDdwWrite;
CStringcStrSendData;
//在这里需要将Unicode字符集转换为ASCII字符集
pSendData=newchar[this->m_CStrWritePipe.GetLength()+1];
memset(pSendData,0,this->m_CStrWritePipe.GetLength()+1);
for(inti=0;i
{
pSendData[i]=(char)this->m_CStrWritePipe.GetAt(i);
}
if(!
WriteFile(hPipeWrite,pSendData,
this->m_CStrWritePipe.GetLength()+1,&dwWrite,NULL))
{
MessageBox(TEXT("给匿名管道发送数据失败..."),
TEXT("提示"),MB_ICONERROR);
return;
}
cStrSendData="给匿名管道发送数据成功:
";
cStrSendData+=this->m_CStrWritePipe;
this->m_CStrWritePipe.Empty();
UpdateData(FALSE);
MessageBox(cStrSendData,TEXT("提示"),MB_ICONINFORMATION);
}
else
{
MessageBox(TEXT("请先输入要发送给匿名管道的数据..."),
TEXT("提示"),MB_ICONERROR);
}
}
//创建SECURITY_ATTRIBUTES结构
voidCNoNamedPipeParentDlg:
:
CreateSecurityAttributes(PSECURITY_ATTRIBUTESpSa)
{
//这里必须将bInheritHandle设置为TRUE,
//从而使得子进程可以继承父进程创建的匿名管道的句柄
pSa->bInheritHandle=TRUE;
pSa->lpSecurityDescriptor=NULL;
pSa->nLength=sizeof(SECURITY_ATTRIBUTES);
}
//用来初始化新进程的STARTUPINFO成员
voidCNoNamedPipeParentDlg:
:
CreateStartUpInfo(LPSTARTUPINFOlpStartUpInfo)
{
memset(lpStartUpInfo,0,sizeof(STARTUPINFO));
lpStartUpInfo->cb=sizeof(STARTUPINFO);
lpStartUpInfo->dwFlags=STARTF_USESTDHANDLES;
//子进程的标准输入句柄为父进程管道的读数据句柄
lpStartUpInfo->hStdInput=hPipeRead;
//子进程的标准输出句柄为父进程管道的写数据句柄
lpStartUpInfo->hStdOutput=hPipeWrite;
//子进程的标准错误处理句柄和父进程的标准错误处理句柄一致
lpStartUpInfo->hStdError=GetStdHandle(STD_ERROR_HANDLE);
}
//创建匿名管道
voidCNoNamedPipeParentDlg:
:
CreateNoNamedPipe(void)
{
SECURITY_ATTRIBUTESsa;
PROCESS_INFORMATIONprocessInfo;
STARTUPINFOstartUpInfo;
CreateSecurityAttributes(&sa);
if(!
CreatePipe(&hPipeRead,&hPipeWrite,&sa,0))
{
MessageBox(TEXT("创建匿名管道失败..."),
TEXT("提示"),MB_ICONERROR);
return;
}
CreateStartUpInfo(&startUpInfo);
if(!
CreateProcess(TEXT("NoNamedPipeChild.exe"),
NULL,NULL,NULL,TRUE,
CREATE_NEW_CONSOLE,NULL,NULL,
&startUpInfo,&processInfo))
{
CloseHandle(hPipeRead);
CloseHandle(hPipeWrite);
hPipeWrite=NULL;
hPipeRead=NULL;
MessageBox(TEXT("创建子进程失败..."),
TEXT("提示"),MB_ICONERROR);
return;
}
else
{
m_PipeIsCreated=TRUE;
//对于processInfo.hProcess和processInfo.hThread
//这两个句柄不需要使用,所以释放资源
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
}
2、子程序
//实现
protected:
HICONm_hIcon;
//生成的消息映射函数
virtualBOOLOnInitDialog();
afx_msgvoidOnPaint();
afx_msgHCURSOROnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msgvoidOnBnClickedBtnWritePipe();
afx_msgvoidOnBnClickedBtnReadPipe();
//保存从父进程得到针对于匿名管道的读写句柄
HANDLEhPipeRead;
HANDLEhPipeWrite;
//分别代表要从匿名管道中读的数据和要写到匿名管道中的数据
CStringm_CStrWritePipe;
CStringm_CStrReadPipe;
//子进程读取匿名管道
voidChildReadPipe(void);
//子进程写匿名管道
voidChildWritePipe(void);
//子进程获取从父进程处继承得到的关于匿名管道的读写句柄
voidGetReadWriteHandleFromParent(void);
//只需要获取一次匿名管道的读写句柄即可
BOOLm_IsGettedParentHandle;
constintdataLength=100;
CNoNamedPipeChildDlg:
:
CNoNamedPipeChildDlg(CWnd*pParent/*=NULL*/)
:
CDialogEx(CNoNamedPipeChildDlg:
:
IDD,pParent)
m_CStrWritePipe(_T(""))
m_CStrReadPipe(_T(""))
{
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
this->m_IsGettedParentHandle=FALSE;
}
voidCNoNamedPipeChildDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialogEx:
:
DoDataExchange(pDX);
DDX_Text(pDX,IDC_EDIT_WRITE_PIPE,m_CStrWri
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 操作系统 进程 通信