进程间通信之CreatePipe
CreatePipe function
创建匿名管道,返回读,写管道的handle。
BOOL WINAPI CreatePipe(
_Out_ PHANDLE hReadPipe,
_Out_ PHANDLE hWritePipe,
_In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,
_In_ DWORD nSize
);
参数:
hReadPipe [out]
返回对管道读的handle
hWritePipe [out]
返回对管道写的handle
lpPipeAttributes [in, optional]
指向SECURITY_ATTRIBUTES结构的指针。SECURITY_ATTRIBUTES决定了子进程是否可以继承管道的读写handle。
如果lpPipeAttributes是NULL,不能继承。
nSize [in]
管道的缓冲空间。只是一个建议值,系统会根据建议值计算出一个合适的值。如果nSize是0,使用缺省值。
返回值:
如果函数执行成功,返回值非0.
如果失败,返回0。可以通过GetLastError获得更多的信息。
说明:
CreatePipe创建包含适当大小缓冲空间的管道,返回通过ReadFile读, WriteFile写缓冲空间的handle.
ReadFile在如下情况返回:写操作完成,已读到请求大小的字节数,或者发生错误。
WriteFile只到写完所有的字节数才会返回。
若管道缓冲空间在写之前已经满了,那么WriteFile将一直不会返回直到ReadFile读管道后有足够的缓冲空间。
匿名管道是通过命名管道实现的。因此,你可以把匿名管道handle作为命名管道handle使用。
为了释放管道使用的资源,应用程序应该关闭那些不再使用的handles。
下面是子进程的代码。它使用继承的标准输入STDIN和输出STDOUT访问父进程创建的管道。
父进程从in.txt读数据,并把这些数据写到管道1中。子进程从管道1中通过STDIN获得数据,再通过STDOUT写到管道2中。父进程之后再从管道2中读取数据并显示。
//client.cpp
#include <windows.h>
#include <stdio.h>#define BUFSIZE 4096 int main(void)
{ CHAR chBuf[BUFSIZE]; DWORD dwRead, dwWritten; HANDLE hStdin, hStdout; BOOL bSuccess; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); hStdin = GetStdHandle(STD_INPUT_HANDLE); if ( (hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE) ) ExitProcess(1); // Send something to this process's stdout using printf.printf("\n ** This is a message from the child process. ** \n");// This simple algorithm uses the existence of the pipes to control execution.// It relies on the pipe buffers to ensure that no data is lost.// Larger applications would use more advanced process control.for (;;) { // Read from standard input and stop on error or no data.bSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL); if (! bSuccess || dwRead == 0) break; // Write to standard output and stop on error.bSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL); if (! bSuccess) break; } return 0;
}
下面的示例展示了如何使用CreateProcess创建子进程。
同时展示了如何通过匿名管道重定向子进程的标准输入和标准输出。
命名管道同样可以用于进程I/O的重定向。
CreatePipe函数使用SECURITY_ATTRIBUTES结构创建可继承的handle。
这些管道指针在STARTUPINFO结构中被指定为子进程的标准输入,输出。
具体的,不妨参考in.txt上的一幅图。
//parent.cpp
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>#define BUFSIZE 4096 HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;HANDLE g_hInputFile = NULL;void CreateChildProcess(void);
void WriteToPipe(void);
void ReadFromPipe(void);
void ErrorExit(PTSTR); int _tmain(int argc, TCHAR *argv[])
{ SECURITY_ATTRIBUTES saAttr; printf("\n->Start of parent execution.\n");// Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) ErrorExit(TEXT("StdoutRd CreatePipe")); // Ensure the read handle to the pipe for STDOUT is not inherited.if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )ErrorExit(TEXT("Stdout SetHandleInformation")); // Create a pipe for the child process's STDIN. if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) ErrorExit(TEXT("Stdin CreatePipe")); // Ensure the write handle to the pipe for STDIN is not inherited. if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )ErrorExit(TEXT("Stdin SetHandleInformation")); // Create the child process.
// g_hChildStd_OUT_Wr and g_hChildStd_IN_Rd will be inherited by childCreateChildProcess();// Get a handle to an input file for the parent.
// This example assumes a plain text file and uses string output to verify data flow. if (argc == 1) ErrorExit(TEXT("Please specify an input file.\n")); g_hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if ( g_hInputFile == INVALID_HANDLE_VALUE ) ErrorExit(TEXT("CreateFile")); // Write to the pipe that is the standard input for a child process.
// Data is written to the pipe's buffers, so it is not necessary to wait
// until the child process is running before writing data.WriteToPipe(); printf( "\n->Contents of %s written to child STDIN pipe.\n", argv[1]);// Read from pipe that is the standard output for child process. printf( "\n->Contents of child process STDOUT:\n\n", argv[1]);ReadFromPipe(); printf("\n->End of parent execution.\n");// The remaining open handles are cleaned up when this process terminates.
// To avoid resource leaks in a larger application, close handles explicitly. return 0;
} void CreateChildProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
{ TCHAR szCmdline[]=TEXT("child");PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo;BOOL bSuccess = FALSE; // Set up members of the PROCESS_INFORMATION structure. ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = g_hChildStd_OUT_Wr;siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;siStartInfo.hStdInput = g_hChildStd_IN_Rd;siStartInfo.dwFlags |= STARTF_USESTDHANDLES;// Create the child process. bSuccess = CreateProcess(NULL, szCmdline, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited 0, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo); // receives PROCESS_INFORMATION // If an error occurs, exit the application. if ( ! bSuccess ) ErrorExit(TEXT("CreateProcess"));else {// Close handles to the child process and its primary thread.// Some applications might keep these handles to monitor the status// of the child process, for example. CloseHandle(piProcInfo.hProcess);CloseHandle(piProcInfo.hThread);}
}void WriteToPipe(void) // Read from a file and write its contents to the pipe for the child's STDIN.
// Stop when there is no more data.
{ DWORD dwRead, dwWritten; CHAR chBuf[BUFSIZE];BOOL bSuccess = FALSE;for (;;) { bSuccess = ReadFile(g_hInputFile, chBuf, BUFSIZE, &dwRead, NULL);if ( ! bSuccess || dwRead == 0 ) break; bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);if ( ! bSuccess ) break; } // Close the pipe handle so the child process stops reading. if ( ! CloseHandle(g_hChildStd_IN_Wr) ) ErrorExit(TEXT("StdInWr CloseHandle"));
} void ReadFromPipe(void) // Read output from the child process's pipe for STDOUT
// and write to the parent process's pipe for STDOUT.
// Stop when there is no more data.
{ DWORD dwRead, dwWritten; CHAR chBuf[BUFSIZE]; BOOL bSuccess = FALSE;HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);for (;;) { bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);if( ! bSuccess || dwRead == 0 ) break; bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL);if (! bSuccess ) break; }
} void ErrorExit(PTSTR lpszFunction) // Format a readable error message, display a message box,
// and exit from the application.
{ LPVOID lpMsgBuf;LPVOID lpDisplayBuf;DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dw,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0, NULL );lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR),TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf);LocalFree(lpDisplayBuf);ExitProcess(1);
}
//in.txt
/*Creating a Child Process with Redirected Input and Output
The example in this topic demonstrates how to create a child process
using the CreateProcess function from a console process.
It also demonstrates a technique for using anonymous pipes to redirect
the child process's standard input and output handles.
Note that named pipes can also be used to redirect process I/O.PipServer PipClientg_hChildStd_IN_Wr g_hChildStd_IN_Rd/STD_INPUT_HANDLE |-----------------------> anonymous pipe <-----------------------|
g_hChildStd_OUT_Rd g_hChildStd_OUT_Wr/STD_OUTPUT_HANDLE*/
说明
1, http://msdn.microsoft.com/en-us/library/windows/desktop/aa365152(v=vs.85).aspx
2, http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
进程间通信之CreatePipe相关推荐
- Windows进程间通信的各种方法
Windows进程间通信的各种方法 原文:Windows进程间通信的各种方法 进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据以及它可利用的系统资源(如文件.管道等)组成. ...
- Windows系统编程之进程间通信
Windows系统编程之进程间通信 标 题: Windows系统编程之进程间通信 作 者: 北极星2003 时 间: 2006-05-25,14:18:36 链 接: http://bbs.pediy ...
- CreatePipe匿名管道通信
管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机.一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来.匿名管道(An ...
- 进程间通信 - 匿名管道实现
引子 前面的两篇博文分别介绍了通过剪贴板和通过邮槽来实现进程之间的通信, 其中剪贴板呢,是用来实现本地两个进程之间的通信, 而邮槽则既可以实现本地两个进程之间的通信,也可以实现本地进程和服务器进程的通 ...
- 管道(Pipe)/createPipe
BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针 PHANDLE hWritePipe, // 指向写句柄的指针 LPSECURITY_ATTRIBUTES ...
- android uri parcel,Android ParcelFileDescriptor实现进程间通信
需求 一个通信通道,实现跨进程的的Socket网络通信. 具体的通信通道的图如下. 需求分析 我们需要一个进程一直做通信通道的事情,业务进程把数据通过进程间通信交给通信进程. 通信进程通过Socket ...
- Windows——进程间通信
进程间通信 进程间通信的概念 Mailslots 关于Mailslots 命名规则 使用 创建 Mailslot 写入 Mailslot 读取Mailslot 管道 关于管道 匿名管道 匿名管道创建 ...
- 进程间通信 IPC interprocess communication
1,管道,FIFO 2, 信号 3,消息队列 4,共享类存 5.文件映射 6.socket (1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行 ...
- Windows下进程间通信
1. WM_COPYDATA 这种方法仅适合于Windows的GUI程序.利用WM_COPYDATA消息来进行进程间通信.其原理是如下: 在x86下,由于保护模式下进程都具有虚拟内存.所以每个进程都拥 ...
- Python 多进程笔记 — 启动进程的方式、守护进程、进程间通信、进程池、进程池之间通信、多进程生产消费模型
1 面向过程启动多进程 Python 操作进程的类都定义在 multiprocessing 模块,该模块提供了一个 Process 类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另 ...
最新文章
- CserialPort类的简单用法
- 2018-2019-1 20189201 《LInux内核原理与分析》第九周作业
- zookeeper配置
- 承载辉煌历史 畅想无线未来
- java散列法的运用实例,Java HashMap compute() 使用方法及示例
- 我们应该搞清楚分支预测
- nginx 的 rewrite 模块
- Swift 2.3- 3.0
- mysql两表查询单个_对两个表进行单个MySQL选择查询是可能的吗?
- Java基础---数组
- Oracle学习技巧
- 微信表白代码,单身汪们还不快收藏!
- Element is not clickable at point,Other element would receive the click: xxx 遇到某个对象Click()不能正常使用?
- MVC5局部视图的调用
- cap 2 加州房价预测
- SYSTEM大法好!!!
- Nginx反向代理解决跨域问题(个人学习总结)
- C# ThoughtWorks.QRCode.dll 生成完美二维码(大小 边距 备注 颜色 LOGO大小背景形状)
- UVALive 4487 - Exclusive-OR -并查集 虚根
- 量子计算到底是什么?
热门文章
- Hadoop之纠删码
- pyqt4的一些相关资料整理
- pyqt5 笔记(三)py2exe 实现代码打包exe
- php获取ip所有方式,php获取用户(客户端)真实IP地址的三种方法
- 开源ext2read代码走读之--“\\\\.\\PhysicalDrive0”意义?
- 程序化广告(二)- 考核指标如CTR/CVR/ROI/ARPU等
- java创建动态数组_动态数组java实现
- 创建虚拟机并加载镜像文件
- 海信电视一直处在Android,【干货收藏】海信电视免root精简教程,去除自带无用软件,替换桌面可实现开机自启动...
- SSDP协议的Python示例