使用重定向的輸入和輸出創建子進程

本主題中的示例演示如何使用控制臺進程中的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.pswp.cn/news/448207.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448207.shtml
英文地址,請注明出處:http://en.pswp.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; 喜歡默默的聽、一個人安安靜靜的聽、長長久久的聽、聽得忘乎所…