2026/3/31 19:16:03
网站建设
项目流程
电子商务建设网站,怎么做dj网站,在线构建网站,wordpress duplicator在这儿下载本节的所有源程序
概述
Windows 引入了多进程和多线程机制。同时也提供了多个进程之间的通信手段#xff0c;包括剪贴板、DDE、OLE、管道等#xff0c;和其他通信手段相比#xff0c;管道有它自己的限制和特点#xff0c;管道实际上是一段共享内存区#xff0…在这儿下载本节的所有源程序概述Windows 引入了多进程和多线程机制。同时也提供了多个进程之间的通信手段包括剪贴板、DDE、OLE、管道等和其他通信手段相比管道有它自己的限制和特点管道实际上是一段共享内存区进程把共享消息放在那里。并通过一些 API 提供信息交换。管道是两个头的东西每个头各连接一个进程或者同一个进程的不同代码按照管道的类别分有两种管道匿名的和命名的按照管道的传输方向分也可以分成两种单向的双向的。根据管道的特点命名管道通常用在网络环境下不同计算机上运行的进程之间的通信当然也可以用在同一台机的不同进程中它可以是单向或双向的而匿名管道只能用在同一台计算机中它只能是单向的。匿名管道其实是通过用给了一个指定名字的有名管道来实现的。使用管道的好处在于读写它使用的是对文件操作的 api结果操作管道就和操作文件一样。即使你在不同的计算机之间用命名管道来通信你也不必了解和自己去实现网络间通信的具体细节。我们简单的介绍一下命名管道的使用。命名管道是由服务器端的进程建立的管道的命名必须遵循特定的命名方法就是 \\.\pipe\管道名当作为客户端的进程要使用时使用\\计算机名\\pipe\管道名 来打开使用具体步骤如下服务端通过函数 CreateNamedPipe 创建一个命名管道的实例并返回用于今后操作的句柄或为已存在的管道创建新的实例。服务端侦听来自客户端的连接请求该功能通过 ConnectNamedPipe 函数实现。客户端通过函数 WaitNamedPipe 来等待管道的出现如果在超时值变为零以前有一个管道可以使用则 WaitNamedPipe 将返回 True并通过调用 CreateFile 或 CallNamedPipe 来呼叫对服务端的连接。此时服务端将接受客户端的连接请求成功建立连接服务端 ConnectNamedPipe 返回 True建立连接之后客户端与服务器端即可通过 ReadFile 和 WriteFile利用得到的管道文件句柄彼此间进行信息交换。当客户端与服务端的通信结束客户端调用 CloseFile服务端接着调用 DisconnectNamedPipe。最后调用函数CloseHandle来关闭该管道。由于命名管道使用时作为客户端的程序必须知道管道的名称所以更多的用在同一“作者”编写的服务器/工作站程序中你不可能随便找出一个程序来要求它和你写的程序来通过命名管道通信。而匿名管道的使用则完全不同它允许你和完全不相干的进程通信条件是这个进程通过控制台“console”来输入输出典型的例子是老的 Dos 应用程序它们在运行时 Windows 为它们开了个 Dos 窗口它们的输入输出就是 console 方式的。还有一些标准的 Win32 程序也使用控制台输入输出如果在 Win32 编程中不想使用图形界面你照样可以使用 AllocConsole 得到一个控制台然后通过 GetStdHandle 得到输入或输出句柄再通过 WriteConsole 或 WriteFile 把结果输出到控制台通常是一个象 Dos 窗口的屏幕上。虽然这些程序看起来象 Dos 程序但它们是不折不扣的 Win32 程序如果你在纯 Dos 下使用就会显示“The program must run under Windows!”。一个控制台有三个句柄标准输入、标准输出和和标准错误句柄标准输入、标准输出句柄是可以重新定向的你可以用匿名管道来代替它这样一来你可以在管道的另一端用别的进程来接收或输入而控制台一方并没有感到什么不同就象 Dos 下的 或者 可以重新定向输出或输入一样。通常控制台程序的输入输出如下(控制台进程output) write ---- 标准输出设备一般是屏幕(控制台进程input) read ---- 标准输入设备一般是键盘而用管道代替后(作为子进程的控制台进程output) write ---- 管道1 ---- read (父进程)(作为子进程的控制台进程input) read ---- 管道2 ---- write (父进程)使用匿名管道的步骤如下使用 CreatePipe 建立两个管道得到管道句柄一个用来输入一个用来输出准备执行控制台子进程首先使用 GetStartupInfo 得到 StartupInfo使用第一个管道句柄代替 StartupInfo 中的 hStdInput第二个代替 hStdOutput、hStdError即标准输入、输出、错误句柄使用 CreateProcess 执行子进程这样建立的子进程输入和输出就被定向到管道中父进程通过 ReadFile 读第二个管道来获得子进程的输出通过 WriteFile 写第一个管道来将输入写到子进程父进程可以通过 PeekNamedPipe 来查询子进程有没有输出子进程结束后要通过 CloseHandle 来关闭两个管道。下面是具体的说明和定义1. 建立匿名管道使用 CreatePipe 原形如下BOOL CreatePipe(PHANDLE hReadPipe, // address of variable for read handlePHANDLE hWritePipe, // address of variable for write handleLPSECURITY_ATTRIBUTES lpPipeAttributes, // pointer to security attributesDWORD nSize // number of bytes reserved for pipe);当管道建立后结构中指向的 hReadPipe 和 hWritePipe 可用来读写管道当然由于匿名管道是单向的你只能使用其中的一个句柄参数中的 SECURITY_ATTRIBUTES 的结构必须填写定义如下typedef struct_SECURITY_ATTRIBUTES{DWORD nLength: //定义以字节为单位的此结构的长度LPVOID lpSecurityDescriptor; //指向控制这个对象共享的安全描述符,如果为NULL这个对象将被分配一个缺省的安全描述BOOL bInheritHandle; //当一个新过程被创建时,定义其返回是否是继承的.供系统API函数使用.}SECURITY_ATTRIBUTES;2. 填写创建子进程用的 STARTUPINFO 结构一般我们可以先用 GetStartupInfo 来填写一个缺省的结构然后改动我们用得到的地方它们是hStdInput -- 用其中一个管道的 hWritePipe 代替hStdOutput、hStdError -- 用另一个管道的 hReadPipe 代替dwFlags -- 设置为 STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW 表示输入输出句柄及 wShowWindow 字段有效wShowWindow -- 设置为 SW_HIDE这样子进程执行时不显示窗口。填写好以后就可以用 CreateProcess 来执行子进程了具体有关执行子进程的操作可以参考上一篇教程《进程控制》3. 在程序中可以用 PeekNamedPipe 查询子进程有没有输出原形如下BOOL PeekNamedPipe(HANDLE hNamedPipe, // handle to pipe to copy fromLPVOID lpBuffer, // pointer to data bufferDWORD nBufferSize, // size, in bytes, of data bufferLPDWORD lpBytesRead, // pointer to number of bytes readLPDWORD lpTotalBytesAvail, // pointer to total number of bytes availableLPDWORD lpBytesLeftThisMessage // pointer to unread bytes in this message);我们可以将尝试读取 nBuffersize 大小的数据然后可以通过返回的 BytesRead 得到管道中有多少数据如果不等于零则表示有数据可以读取。4. 用 ReadFile 和 WriteFile 来读写管道它们的参数是完全一样的原形如下ReadFile or WriteFile(HANDLE hFile, // handle of file to read 在这里使用管道句柄LPVOID lpBuffer, // address of buffer that receives data 缓冲区地址DWORD nNumberOfBytesToRead, // number of bytes to read 准备读写的字节数LPDWORD lpNumberOfBytesRead, // address of number of bytes read实际读到的或写入的字节数LPOVERLAPPED lpOverlapped // address of structure for data 在这里用 NULL);5. 用 CloseHandle 关闭管道一和管道二的 hReadPipe和 hWritePipe 这四个句柄。下面给出了一个例子程序这个程序是上篇教程《进程控制》的例子的扩充如果你对有的 api 感到陌生的话请先阅读上一篇教程。源程序 - 汇编源文件DEBUG equ 0;; Programmed by 罗云彬, bigluotelekbird.com.cn; Website: http://asm.yeah.net; LuoYunBins Win32 ASM page (罗云彬的编程乐园);; 版本信息; 汇编教程附带例子程序 - 管道例子;.386.model flat, stdcalloption casemap :none ; case sensitive;; Include 数据;include windows.incinclude user32.incinclude kernel32.incinclude comctl32.incinclude comdlg32.incinclude gdi32.incincludelib user32.libincludelib kernel32.libincludelib comctl32.libincludelib comdlg32.libincludelib gdi32.lib;; Equ 数据;ICO_MAIN equ 1000MENU_MAIN equ 2000IDM_EXEC equ 2001IDM_EXIT equ 2002F_RUNNING equ 0001h ;进程在运行中;; 数据段;.data?stStartUp STARTUPINFO ?hInstance dd ?hMenu dd ?hWinMain dd ?hWinText dd ?hFont dd ?hRunThread dd ?hRead1 dd ?hWrite1 dd ?hRead2 dd ?hWrite2 dd ?szBuffer db 512 dup (?)dwFlag dd ?;.dataszMenuExecute db 连接 MS-DOS 方式,0szExcuteError db 启动应用程序错误,0szCaption db 管道示例程序 ... http://asm.yeah.net,0szClassName db PipeExample,0;szDllName db riched32.dll,0;szClassNameRedit db RichEdit,0szDllName db riched20.dll,0szClassNameRedit db richedit20a,0szCommand db c:\command.com,0stLogFont LOGFONT 24,0,0,0,FW_NORMAL,\0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\CLIP_STROKE_PRECIS,DEFAULT_QUALITY,\DEFAULT_PITCH or FF_SWISS,Fixedsys;; 代码段;.codeif DEBUGinclude Debug.asmendifinclude Win.asm;********************************************************************; 执行程序用的线程; 1. 用 CreateProcess 建立进程; 2. 用 WaitForSingleOject 等待进程结束;********************************************************************_RunThread proc uses ebx ecx edx esi edi,\dwParam:DWORDlocal stSecurity:SECURITY_ATTRIBUTESlocal dwExitCodelocal dwBytesReadlocal stRange:CHARRANGEor dwFlag,F_RUNNING;********************************************************************; “执行”菜单改为“结束”;********************************************************************invoke EnableMenuItem,hMenu,IDM_EXEC,MF_GRAYEDinvoke