Windows 95作为一个多任务操作系统,其重要特征之一是引入了多
进程和多线程机制。其中每个进程都有私有的虚拟地址空间,可以创建多个线
程,每个线程被分配一个时间片,当前执行的线程在其时间片耗尽时挂起,让
其他线程运行。由于各时间片很小,所以看起来就像是多个线程在同时工作。
有时用户运行的进程之间毫无关系,但是进程之间信息的交换则能产
生协作效果,这样就可以完成某些单个进程所不能完成的任务。Windows 95可
以使用多种通信手段,包括剪贴板、DDE、OLE等,而且还增加了一些新的手段,
其中管道是用来在不同程序之间交换信息的简便的通信机制。与其它手段不同,
管道没有正式的标准或协议来控制信息传递,所以与DD E会话这样的机制相比,
管道更易于使用、更加灵活。管道实际上是一段共享内存区,进程把共享消息放在这里。
本文将在VC++4.1环境下介绍一个父进程和其子进程的通信实例。
在父进程Parent窗口中按一下鼠标左键,就会产生一个管道(Pipe)并启动子
进程Child,且从(Pipe)一端发送信息,同时Child启动后会创建一个工作线
程,专门用来从管道的另一端读入数据。父进程通过菜单项的控制来改变图
形形状参数,并传给Child使之在自己的窗口中绘出响应的图形。下面分别就
父进程Parent和子进程Child来进行说明。
父进程Parent
在父进程Parent中,我们将创建管道和启动子进程。首先说明几个相关函数。
创建进程函数:
BOOL CreateProcess(
LPCTSTR lpApplicationName, //应用模式指针
LPTSTR lpCommandLine, // 命令行字符串
LPSECURITY_ATTRIBUTES lpProcessAttributes,
// 进程安全性指针
LPSECURITY_ATTRIBUTES lpThreadAttributes,
// 主线程安全性指针
BOOL bInheritHandles,// 是否继承句柄
DWORD dwCreationFlags,// 进程类型与优先级
LPVOID lpEnvironment,// 环境块指针
LPCTSTR lpCurrentDirectory,// 当前目录
LPSTARTUPINFO lpStartupInfo,
// STARTUPINFO结构指针
LPPROCESS_INFORMATION lpProcessInformation);
// 新进程信息
创建管道函数:
BOOL CreatePipe(
PHANDLE hReadPipe, // 读句柄变量地址
PHANDLE hWritePipe,// 写句柄变量地址
LPSECURITY_ATTRIBUTES lpPipeAttributes,
// 安全属性指针
DWORDnSize );//管道缓冲区大小
写管道函数:
BOOL WriteFile(
HANDLE hFile;//写入文件句柄
LPCVOID lpBuffer;//写入数据指针
DWORD nNumberOfBytesToWrite;
//要写入字节数量
LPDWORD lpNumberOfBytesWritten;
//已写入字节数地址
LPOVERLAPPED lpOverlapped );
//异步I/O结构指针
下面从编程角度讨论其实现步骤:
1.利用AppWizard(EXE)产生Parent应用框架,然后在文件Parentview.cpp
头部加入#in clude<global.h>,其中文件global.h定义了两个进程用
于相互通信的结构和常量值。代码如下:
Global.h 共享变量头文件:
typedef struct Figure
{int iShape;// 图形控制参数
} FIGURE,*PFIGURE;
#define ID_RECT 32771
#define ID_ELLIPSE 32772
#define ID_TERMINATE 32773
2.使用ClassWizard工具:选择对应于CParentView类的消息WM_LBUTTONDOWN,
选择AddFu nction键,增加函数OnLButtonDown()。在主菜单资源中加入Rect、
Ellipse、Terminate菜单项,ID分别为IDC_RECT、IDR_ELLIPSE、IDR_TERMINATE,
并在ClassWizard中加入相应函数。
在文件Parentview.h中加入如下代码:
public:
BOOL SendCommand();//发送信息
HANDLE hProcess; //进程句柄
HANDLE hpipeWrite; //管道写句柄
FIGURE figure;
本文给出Parentview.cpp的部分程序代码。
编者注:源代码发表在:http://www.computerworld.com. cn/98/skill/default. htm。
子进程Child
Child启动之后,立刻创建一个新的线程,并在新线程中执行读管道操作,
利用读得的参数使主窗口绘出形状。读管道函数为:
BOOL ReadFile(
HANDLE hFile,// 读入文件句柄
LPVOID lpBuffer, // 读入数据缓冲区地址
DWORD nNumberOfBytesToRead;
// 要读入字节数量
LPDWORD lpNumberOfBytesRead,;
// 已读入字节数地址
LPOVERLAPPED lpOverlapped );
// 异步I/O结构指针
首先,从MFC类库中创建新线程,使用ClassWizard工具:选择AddClassNew,
输入类名CT hr,在基类列表框中选择“CWinThread",按下Create按钮,生成
线程类CThr。然后修改程序代码。本文给出部分源程序。
结论
运行本文例程,在父进程Parent窗口中按一下鼠标左键,就会产生一个Pipe并
启动子进程Child;在Parent中选中菜单项Rect或Ellipse时,Child窗口中就会
分别绘出矩形和椭圆;选中Terminate时,就会中断通信。以上介绍的是匿名管道,
若要增加通信的灵活性还可采用命名管道NamedPipe,读者可尝试实现。