使用重定向的输入和输出创建子进程

本主题中的示例演示如何使用控制台进程中的CreateProcess函数创建子进程。它还演示了一种使用匿名管道重定向子进程的标准输入和输出句柄的技术。请注意,命名管道也可用于重定向进程I / O.

所述CreatePipe函数使用SECURITY_ATTRIBUTES结构来创建可继承句柄读写两个管道的端部。一个管道的读取端用作子进程的标准输入,另一个管道的写入端是子进程的标准输出。这些管道句柄在STARTUPINFO结构中指定,这使它们成为子进程继承的标准句柄。

父进程使用这两个管道的相反端写入子进程的输入并从子进程的输出中读取。如STARTUPINFO结构中所指定的,这些句柄也是可继承的。但是,不得继承这些句柄。因此,在创建子进程之前,父进程使用SetHandleInformation函数来确保不能继承子进程的标准输入的写句柄和子进程的标准输入的读句柄。有关更多信息,请参阅管道。

以下是父进程的代码。它需要一个命令行参数:文本文件的名称。

#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. 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);
}

以下是子进程的代码。它使用STDIN和STDOUT的继承句柄来访问父级创建的管道。父进程从其输入文件中读取并将信息写入管道。子进程使用STDIN通过管道接收文本,并使用STDOUT写入管道。父节点从管道的读取端读取并将信息显示到其STDOUT。

#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手动挡停车时挂档有技巧

徐小姐来电&#xff1a;我家的汽车要年检了&#xff0c;前几天&#xff0c;工作人员帮我把车子开进检测站去检测&#xff0c;开回来后停在原位上&#xff0c;然后把钥匙交给我。我拿钥匙一点火&#xff0c;车子就突然往前动了&#xff0c;根本没有时间反应&#xff0c;已经撞到…

LOJ 3156: 「NOI2019」回家路线

题目传送门&#xff1a;LOJ #3156。 题意简述&#xff1a; 有一张 \(n\) 个点 \(m\) 条边的有向图&#xff0c;边有两个权值 \(p_i\) 和 \(q_i\)&#xff08;\(p_i<q_i\)&#xff09;表示若 \(p_i\) 时刻在这条边的起点&#xff0c;则 \(q_i\) 时刻能到达这条边的终点。 你需…

线程池概述

线程池 一个线程池的工作线程代表应用程序的高效执行异步回调的集合。线程池主要用于减少应用程序线程的数量并提供工作线程的管理。应用程序可以对工作项进行排队&#xff0c;将工作与可等待的句柄相关联&#xff0c;根据计时器自动排队&#xff0c;并与I / O绑定。 线程池架…

WEB 请求处理二:Nginx 请求 反向代理

上一篇《WEB请求处理一&#xff1a;浏览器请求发起处理》&#xff0c;我们讲述了浏览器端请求发起过程&#xff0c;通过DNS域名解析服务器IP&#xff0c;并建立TCP连接&#xff0c;发送HTTP请求。本文将讲述请求到达反向代理服务器的一个处理过程&#xff0c;比如&#xff1a;在…

方向盘的正确驾驭方法

如果问您油门踏板和方向盘哪个与驾驶员最“亲密”&#xff0c;您会选择谁呢&#xff1f;恐怕还是方向盘吧。如果汽车行驶过程中您的双手同时离开了方向盘&#xff0c;那么事故的隐患也就随之而来。下面我们就为您全面介绍汽车方向盘的正确使用方法。专家介绍&#xff0c;握方向…

SQL server 2005中无法新建作业(Job)的问题

客户端是使用企业管理其&#xff08;Management Studio&#xff09;新建job&#xff0c;总是无法创建&#xff0c;查找了很多资料&#xff0c;有的说是需要sp2, 但有的又说不是... ... 没有时间去研究为什么&#xff0c;但确有一种方法解决&#xff1a;到服务器端去创建job&…

线程池API

线程池API 线程池应用程序编程接口&#xff08;API&#xff09;使用基于对象的设计。以下每个对象都由用户模式数据结构表示&#xff1a; 池对象是一组可用于执行工作的工作线程。每个进程可以根据需要创建具有不同特征的多个隔离池。每个进程都有一个默认池。清理组与一组回…

WEB 请求处理 一:浏览器 请求发起处理

最近&#xff0c;终于要把《WEB请求处理系列》提上日程了&#xff0c;一直答应小伙伴们给分享一套完整的WEB请求处理流程&#xff1a;从浏览器、Nginx、Servlet容器&#xff0c;最终到应用程序WEB请求的一个处理流程&#xff0c;前段时间由于其他工作事情的安排&#xff0c;一直…

离合器半联动探秘

离合器踏板作用是切断发动机和变速箱之间的动力&#xff0c;有利于起步、变速、和停车。那么如何更好的使用它呢&#xff1f; 离合器的五种状态示意图 离合器半联动的使用方法揭密如下&#xff1a; 离合器半联动的使用探密之一 将离合器抬到车开始动时你就别再抬了&#xff0c;…

Biztalk Server 2006安装配置

前段时间收到了来自beta.microsoft.com的BTS20006 Beta2的下载地址&#xff0c;这两天对它进行了一番安装配置。下面把一些经过和步骤和大家分享一下&#xff0c;手中有一些去年的Biztalk Server2004版本的培训资料&#xff0c;里面有11个Lab。需要的朋友请留下mail&#xff0c…

apache 官方 Dubbo 文档

只是分享、记录一下 dubbo 的文档地址&#xff1a;apache 官方 Dubbo 文档 其页面内容如下&#xff1a;&#xff08;我是用 chrome 直接右键翻译的&#xff0c;原文档是英文的&#xff09;

制动踏板是什么?

制动踏板就是脚刹&#xff08;行车制动器&#xff09;的踏板&#xff0c;使运行中的机车、车辆及其他运输工具或机械等停止或减低速度的动作。制动的一般原理是在机器的高速轴上固定一个轮或盘&#xff0c;在机座上安装与之相适应的闸瓦、带或盘&#xff0c;在外力作用下使之产…

CSS Framework 960 Grid System (收)

CSS框架 &#xff1a;960 Grid System 官网&#xff1a;http://960.gs/ 什么是框架&#xff1f;框架是一种你能够使用在你的web项目中概念上的结构。CSS框架一般是CSS文件的集合&#xff0c;包括基本风格的字体排版&#xff0c;表单样式&#xff0c;表格布局等等&#xff0c;比…

使用线程本地存储

线程本地存储&#xff08;TLS&#xff09;使同一进程的多个线程能够使用由TlsAlloc函数分配的索引来存储和检索线程本地的值。在此示例中&#xff0c;在进程启动时分配索引。当每个线程启动时&#xff0c;它会分配一个动态内存块&#xff0c;并使用TlsSetValue函数在TLS槽中存储…

发动机的工作原理,你知道吗?

http://auto.jxedt.com/info/5352.htm 发动机是汽车的动力装置&#xff0c;性能优劣直接影响到汽车性能&#xff0c;发动机的类型很多&#xff0c;结构各异&#xff0c;以适应不同车型的需要。按发动机使用燃料划分&#xff0c;可分成汽油发动机和柴油发动机等类别。按发动机汽…

官方文档: Dubbo 框架设计、模块说明、依赖关系

以下内容全文转自 apache 官方 dubbo文档&#xff1a;http://dubbo.apache.org/en-us/docs/dev/design.html 框架设计 图片描述&#xff1a; 浅蓝色背景的左侧区域显示服务用户界面&#xff0c;浅绿色背景的右侧区域显示服务提供者界面&#xff0c;中心区域显示两个侧面界面。…

那些花儿

今天上海下雨了&#xff0c;心绪也变得低落&#xff0c;突然很想念宿舍的姐妹。毕业后就自作聪明地和她们失去了联系&#xff0c;今天去QQ群遛了一圈。虹结婚了&#xff0c;敏还是活得那么潇洒&#xff0c;笑也在努力地生活... 人生啊&#xff01;总是在向前走&#xff0c;遇…

CreateRemoteThread函数

CreateRemoteThread函数 创建在另一个进程的虚拟地址空间中运行的线程。 使用CreateRemoteThreadEx函数创建在另一个进程的虚拟地址空间中运行的线程&#xff0c;并可选择指定扩展属性。 语法 HANDLE CreateRemoteThread(HANDLE hProcess,LPSECURITY_ATTRI…

防火墙问题 Linux系统 /etc/sysconfig/路径下无iptables文件

虚拟机新装了一个CentOs7&#xff0c;然后做防火墙配置的时候找不到iptables文件&#xff0c;解决方法如下&#xff1a; 因为默认使用的是firewall作为防火墙&#xff0c;把他停掉装个iptable systemctl stop firewalld systemctl mask firewalld yum install -y iptables yum …

如果风 知道 ... 如果云 知道 ...

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 //《心灵之音》----- Bandari 来自酷狗。 一直很喜欢听歌&#xff1a; 喜欢默默的听、一个人安安静静的听、长长久久的听、听得忘乎所…