孙鑫vc++ 17 进程间通信(2) 匿名管道

一、基础知识

1.匿名管道

匿名管道是一个未命名的、单向管道,通常用来在一个父进程和一个子进程之间传输数据。匿名管道只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。

二、从代码进行分析

1.父进程

//管道的创建

void CParentView::OnPipeCreate()
{
 // TODO: Add your command handler code here
 SECURITY_ATTRIBUTES sa;
 
 sa.bInheritHandle = TRUE;
 sa.lpSecurityDescriptor = NULL;
 sa.nLength = sizeof(SECURITY_ATTRIBUTES);

//此处创建管道,hRead和hWrite分别为 从管道读取数据的句柄 和 向管道写入数据的句柄

 if (!CreatePipe(&hRead,&hWrite,&sa,0))
 {
  ::MessageBox(m_hWnd,_T("创建管道失败!"),NULL,MB_OK);
  return;
 }

 STARTUPINFO sui;
 ZeroMemory(&sui,sizeof(STARTUPINFO));//此函数用来给 STARTUPINFO数据结构开辟内存
 sui.dwFlags = STARTF_USESTDHANDLES;
 sui.hStdInput = hRead;
 sui.hStdOutput = hWrite;
 sui.cb = sizeof(STARTUPINFO);
 sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);

 PROCESS_INFORMATION pi;

//访问指定文件夹中的exe文件,利用此文件来启动子进程

 if (!CreateProcess(_T("..\\Debug\\Child.exe"),NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi))
 {
  CloseHandle(hRead);
  CloseHandle(hWrite);
  hRead = NULL;
  hWrite = NULL;
  ::MessageBox(m_hWnd,_T("创建子进程失败!"),NULL,MB_OK);
  return;
 }
 else
 {

//系统首先为新创建的进程创建一个进程内核对象和一个线程内核对象,但是在CreateProcess函数返回之前

//此函数会去访问新的进程内核对象和线程内核对象,在其进行访问的时候,就给这两个内核对象的内核计数

//加一,所以先用 CloseHandle给这两个对象各减一,等进程停止运行的时候,需要系统再为这两个对象减一

//此时这两个内核对象的计数都为0,就可以被释放了
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
 }
 
}

 

//从管道读取数据

void CParentView::OnPipeRead()
{
 // TODO: Add your command handler code here
 char buf[100];
 DWORD dwRead;
 if (!ReadFile(hRead,buf,100,&dwRead,NULL))
 {
  ::MessageBox(m_hWnd,_T("读取数据失败!"),NULL,MB_OK);
  return;
 }
 ::MessageBox(m_hWnd,(LPCTSTR)buf,NULL,MB_OK);
}

 

//向管道写入数据

void CParentView::OnPipeWrite()
{
 // TODO: Add your command handler code here
 char buf[] = "http://www.sunxin.org";
 DWORD dwWrite;
 if (!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  ::MessageBox(m_hWnd,_T("写入数据失败!"),NULL,MB_OK);
  return;
 }
}

2.子进程

//从管道读取数据

void CChildView::OnPipeRead()
{
 // TODO: Add your command handler code here
 char buf[100];
 DWORD dwRead;
 if (!ReadFile(hRead,buf,100,&dwRead,NULL))
 {
  ::MessageBox(m_hWnd,_T("读取数据失败!"),NULL,MB_OK);
  return;
 }
 ::MessageBox(m_hWnd,(LPCTSTR)buf,NULL,MB_OK);
}

 

//向管道写入数据

void CChildView::OnPipeWrite()
{
 // TODO: Add your command handler code here
 char buf[] = "子进程写入数据";
 DWORD dwWrite;
 if (!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  ::MessageBox(m_hWnd,_T("写入数据失败!"),NULL,MB_OK);
  return;
 }
}

 

//得到管道的读写句柄

void CChildView::OnInitialUpdate()
{
 CView::OnInitialUpdate();

 // TODO: Add your specialized code here and/or call the base class

 hRead = GetStdHandle(STD_INPUT_HANDLE);
 hWrite = GetStdHandle(STD_OUTPUT_HANDLE);
}

三、OnInitialUpdate函数的引申

关于构造函数,Create,OnCreate, OnInitialUpdate四者关系
时间上,调用先后顺序不同,构造函数生成本类的对象,但没有产生窗口,Create产生了窗口但没产生窗口里的内容, OnCreate只是产生窗口的基本结构如产生控件,而在OnInitialUpDate()中,主要初始化视图中的控件等。

Create,OnCreate,OnInitalUpdate调用时机。

Create实际创建窗口 

Create函数创建窗口的实质是,产生WM_CREATE消息,而响应WM_CREATE消息的是OnCreate函数。 

Create函数先调用,OnCreate函数后调用。

在Create调用完成后将产生视图基本结构,主窗口将向所有子窗口发送WM_INITIALUPDATE消息,次消息将引起视图类虚函数OnInitialUpdate调用。

四、需要掌握的函数

(1)CreateProcess

(2)CreatePipe

(3)ZeroMemory

(4)GetStdHandle

(5)CloseHandle

(6)ReadFile

(7)WriteFile

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值