进程间通信之CreatePipe

进程间通信之CreatePipeCreatePipefunction创建匿名管道,返回读,写管道的handle。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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 child
   
   CreateChildProcess();

// 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                     PipClient

g_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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159381.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 数据库中的having语句_sql的having语句

    数据库中的having语句_sql的having语句SQL语句HAVING的用法HAVING语句通常与GROUPBY子句及聚集函数COUNT,AVG,SUM,MAX,MIN语句联合使用,用来过滤由GROUPBY语句返回的记录集,通常跟在GROUPBY后边作用相当于WHERE。where子句后边是指定行所对应的条件,并且不能含有聚集函数,而HAVING后边是指定组所对应的条件,可以含有聚合函数。HAVING语句的存在弥补了WHERE关键字不能与聚集函数联合使用的不足。我们可以这样理解:where筛选的是行(一个元组),而having筛选的是组(多

  • 这些年我是如何在知乎安稳引流不被封号的

    这些年我是如何在知乎安稳引流不被封号的

  • Rollup Bridge 介绍(三):Celer cBridge

    Rollup Bridge 介绍(三):Celer cBridge直播预告今晚7:30,我们邀请了Arweave生态头部项目everFinance带你玩转Arweave!敲黑板:观看直播还有机会获得丰厚ARtoken奖励与惊喜小礼品!C…

  • 最短路径问题—Dijkstra算法详解

    最短路径问题—Dijkstra算法详解前言Nobodycangobackandstartanewbeginning,butanyonecanstarttodayandmakeanewending.Name:WillamTime:2017/3/81、最短路径问题介绍问题解释:从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径解决问题的算法:…

  • idea的安装_theia ide

    idea的安装_theia idetheia-ide是一个能运行在浏览器里的开发环境,对常用语言都有很好的支持。非常适合在服务器上运行。本文介绍theia在docker环境下的安装和使用。首次运行基本版,包含基本的编辑功能dockerrun-it-p3000:3000-v"$(pwd):/home/project:cached"theiaide/theia:latest完整版dockerrun-it…

  • android studio飞机大战游戏带注释源码教程(多线程)[通俗易懂]

    android studio飞机大战游戏带注释源码教程(多线程)[通俗易懂]第一次发博客,学了3天的androidstudio还有一点以前的java基础做了个飞机大战的游戏游戏比较简单大概就这几个功能1.会动的背景2.我的飞机3.发射子弹3.敌人飞机第一步新建一个项目我用的是Android4.4版本新建好项目之后xml文件之类的什么都不用管先新建个类叫做huahua.javapackagecom.dahuijii.liziguo;importandroid.c…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号