网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
源代码在线查看: 17.2.4 子进程的实现.txt
17.2.4 子进程的实现
下面开始编写利用匿名管道实现父子进程间通信的子进程程序,同样,也新建一个单文档类型的 MFC
应用程序,工程取名为: Child,并将该工程添加到上面 Parent程序所在的工作区中,同时设置该
工程所在的目录与上述 Parent工程的目录平级。
然后为 Child工程增加一个子菜单,名称为"匿名管道"。接着,为该子菜单添加两个菜单项,并分
别为它们添加相应的命令响应函数,本例选择 CChildView类接收这些命令响应函数。各菜单项的 B、
名称,以及响应函数如表 17.6所示。
表 17.6添加的菜单项及相应的晌应函数
B 菜单名称 响应函数
IDM PIPE READ 读取数据 OnPipeRead
IDM PIPE WRITE 写入数据 OnPipeWrite
同样,为 CChildView类增加以下两个私有成员变量,即两个句柄,它们将分别作为匿名管道的读取
和写入句柄。
private:
HANDLE hWrite;
HANDLE hRead;
并在 CChildView类的构造函数中将它们都初始化为 NULL:
CChildView :: CCh工 ldV工 ew ()
11 TODO: add construction code here
hRead=NULL;
hWrite=NULL;
然后在 CChildView类的析构函数中,如果判断出这两个变量有值,则调用 CloseHandle函数关闭这
两个变量。
CChildView: : -CChildView ()
if(hRead)
CloseHandle(hRead);
if(hWrite)
CloseHandle(hWrite) ;
1.获得管道的读取和写入句柄
为了利用父进程创建的匿名管道进行通信,子进程中,首先就要得到子进程的标准输入和输出句柄,
这可以在 CChildView类窗口完全创建成功后去获取。因此,根据前面的知识,我们可以为
CChildView类增加虚函数: OnInitialUpdate,这个函数是当窗口成功创建之后,第一个调用的函数。
在此函数中可以通过调用 GetStdHandle函数获取子进程的标准输入和输出句柄,具体代码如例
17-6所示。
例 17-6
void CChildView :: OnInitialUpdate ()
CView : :On工 nitialUpdate() i
11 TODO: Add your specialized code here and/ or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE) ;
hWrite=GetStdHandle(STD_OUTPUT_HANDLE) ;
2.读取数据
得到匿名管道的读取和写入句柄后,就可以利用这些管道句柄读取和写入数据了。接下来,应该在
OnPipeRead函数中实现从父进程创建的管道上读取数据。子进程中读取数据的实现与上面 Parent
程序中读取数据的实现是一样的,即具体实现代码如例 17-7所示。
例 17-7
void CChildView::OnPipeRead()
// TODO: Add your command handler code here
char buf [100] ;
DWORD dwRead;
if(!ReadFile(hRead, buf , 100 , &dwRead, NULL))
MessageBox("读取数据失败 !");
return;
MessageBox(buf);
3.写入数据
在OnPipeWrite函数中,实现向父进程创建的管道中写入数据的功能,子进程中写入数据的实现与上
面 Parent程序中写入数据的实现是一样,但为了区分父子进程写入的数据,这里让子进程写入不同
的数据,具体实现代码如例 17-8所示。
.
例 17-8
void CChildView::OnPipeWrite()
// TODO: Add your command handler code here
char buf [] ="匿名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hWrite, buf , strlen(buf)+1 , &dwWrite, NULL))
MessageBox("写入数据失败!");
return;
最后,利用 Build命令生成 Child程序。
以上就是利用匿名管道实现进程间通信的子进程程序的实现。在子进程中,只需要获得父进程创建
的匿名管道的读、写句柄,然后就可以利用这两个句柄实现从管道读取数据,或者向管道写入数据。
现在就可以测试一下 Parent进程和 Child进程的通信效果。如果我们按照通常启动程序的方法,独
立地启动这两个进程,那么这时这两个进程之间是否可以进行通信呢?读者应注意,对于匿名管道来
说,它只能在父、子进程之间进行通信。两个进程如果想要具有
父子关系,必须由父进程通过调用CreateProcess函数去启动子进程。像通常那样单独启动这两个进
程,它们之间并没有父子关系,并不会因为程序名一个是 "Parent",另一个是 "Child飞它们之间
就具有父子关系了。对于子进程来说,它必须由父进程来启动。所以这里我们应该先启动Parent程
序,然后选择【创建管道】菜单项来启动子进程。接着,可以在Parent程序中选择【写入数据】菜
单项,即在父进程中向创建的匿名管道写入数据,然后在 Child程序中选择【读取数据】菜单项,
将会看到 Child程序弹出一个消息框,提示接收到数据: ''http://www.sunxin.o屯",如图 17.4
所示。同样地,子进程也可以向匿名管道
写入数据,在父进程中读取数据。即在Child程序中选择【写入数据】菜单项,然后在Parent程序中
选择【读取数据】菜单项,将会看到Parent程序弹出一个消息框,提示接收到数据:"匿名管道测试
程序",如图 17.5所示。
图 17.5利用匿名管道实现父子进程间通信程序运行结果 (二)另外,利用匿名管道还可以实现在同
一个进程内读取和写入数据。例如,可以在Parent进程中先通过单击【创建管道】菜单项创建匿名
管道,接着单击【写入数据】菜单项,向
匿名管道写入数据,然后单击 【读取数据】菜单项,从该管道读取数据。 将会看到程序的
结果也是正确的。
以上就是对匿名管道的使用,它主要是用来在父子进程间进行通信。 利用匿名管道实
现父子进程间通信时,需要注意一点:因为匿名管道没有名称,所以只能在父进程中调用
CreateProcess函数创建子进程时,将管道的读、写句柄传递给子进程。