C++匿名管道详解及简单案例(基于VS2013)
首先放一張程序的運行圖(程序下載地址),這里是父進程的一個命令行執行情況:
父進程的源文檔中已經將子進程的執行程序放在了相對路徑下,各位下載后直接運行父進程進行Debug即可得到效果,子進程程序供學習參考使用,這里先放上父進程的代碼:
int main(int argc, char* argv[])
{
?
?? ?SECURITY_ATTRIBUTES sa; ?//定義一個安全結構體類型的變量Sa
?? ?sa.bInheritHandle = TRUE;//讓子進程可以繼承父進程創建的匿名管道的讀寫句柄
?? ?sa.lpSecurityDescriptor = NULL;//讓系統為創建的匿名管道賦予默認的安全描述符
?? ?sa.nLength = sizeof(SECURITY_ATTRIBUTES);//得到結構體(SECURITY_ATTRIBUTES)的長度
?? ?if (!CreatePipe(&hRead, &hWrite, &sa, 0))//判斷創建匿名管道是否成功
?? ?{
?? ??? ?cout << "創建匿名管道失敗!\n";
?? ??? ?return 0;
?? ?}
?? ?else
?? ??? ?cout << "成功創建匿名管道!\n";
?? ?//如果創建匿名管道成功,就啟動子進程,并將匿名管道的讀寫句柄傳遞給子進程
?? ?STARTUPINFO sui;//創建子進程的函數需要的一個結構體類型的值
?? ?PROCESS_INFORMATION pi;
?? ?ZeroMemory(&sui, sizeof(STARTUPINFO));//將其余的成員全部置零,避免造成不好的影響
?? ?sui.cb = sizeof(STARTUPINFO);//cb用來存放結構體變量STARTUPINFO的長度
?? ?sui.dwFlags = STARTF_USESTDHANDLES;//標志成員,表示當前STARTUPINFO結構體的標準輸入,標準輸出和標準錯誤句柄有用
?? ?sui.hStdInput = hRead;
?? ?sui.hStdOutput = hWrite;//將子進程的標準輸入輸出句柄分別設置為管道的讀、寫句柄
?? ?sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);
?? ?sui.wShowWindow = SW_SHOW; //隱藏命令行窗口
?? ?sui.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
?? ?WriteMsg();
?? ?if (!CreateProcess(NULL, "child.exe", NULL, NULL,
?? ??? ?TRUE, 0, NULL, NULL, &sui, &pi))//創建子進程(十個參數)
?? ?{
?? ??? ?CloseHandle(hRead);
?? ??? ?CloseHandle(hWrite);//關閉句柄,將內核對象的使用計數減少1,這樣當操作系統發現內核對象的使用計數為0時,將清除內核對象。
?? ??? ?hRead = NULL;
?? ??? ?hWrite = NULL;
?? ??? ?cout << "創建子進程失敗!";
?? ??? ?return 0;
?? ?}
?? ?else
?? ?{
?? ??? ?CloseHandle(pi.hProcess);
?? ??? ?CloseHandle(pi.hThread);
?? ?}
?
?
?? ?Sleep(200);
?? ?ReadMsg();
?? ?return 0;
}
在說明創建函數之前我們需要先了解程序代碼中涉及的幾個結構體具體是干什么的(詳細請查詢庫)
STARTUPINFO:用于指定新進程的主窗口特性的一個結構。
SECURITY_ATTRIBUTES:一個與安全相關的結構體。
PROCESS_INFORMATION:在創建進程時相關的數據結構之一,該結構返回有關新進程及其主線程的信息。
其余的代碼的具體含義已經給予了非常詳細的注釋,這里只單說一下Create函數的各個參數的具體含義
CreateProcess("child.exe", NULL, NULL, NULL,TRUE, 0, NULL, NULL, &sui, &pi)
這里一共有十個參數
1、子進程應用程序的進程名
2、指定命令行參數,默認為NULL
3|4、進程和線程安全屬性,默認為NULL,即使用系統默認安全屬性
5、值為TRUE時,讓父進程的每個可繼承的打開句柄都能被子進程繼承
6、創建標志,如不需要,置值為0
7、讓新進程使用調用進程的環境、默認為NULL
8、讓父進程和子進程擁有同樣的驅動器和路徑,默認為NULL
9、STARTUPINFO結構體實例化對象的地址(sui地址)
10、PROCESS_INFORMATION的地址(pi地址)
讀數據代碼:
void ReadMsg()
{
?? ?char buf1[512];
?? ?DWORD dwRead;
?? ?if (!ReadFile(hRead, buf1, 512, &dwRead, NULL))
?? ?{
?? ??? ?cout<<"讀取數據失敗!";
?? ??? ?return;
?? ?}
?? ?else
?? ?{
?? ??? ?cout << "管道中讀取數據為:"<<buf1;
?? ??? ?system("pause");
?? ?}
}
寫數據代碼:
void WriteMsg()
{
?? ?char buf[100];
?? ?cout << "請輸入你要發給子進程的消息:\n";
?? ?cin >> buf;
?? ?DWORD dwWrite;
?? ?if (!WriteFile(hWrite, buf, strlen(buf), &dwWrite, NULL))
?? ?{
?? ??? ?cout << "寫入數據失敗!";
?? ??? ?return;
?? ?}
?? ?else
?? ??? ?cout << "成功寫入數據!\n";
}
相對于父進程,子進程相應就要簡單很多了:
子進程讀信息:
void ReadMsg()
{
?
?? ?DWORD dwRead;
?? ?if (!ReadFile(hRead, buf, 100, &dwRead, NULL))
?? ?{
?? ??? ?cout<<"讀取數據失敗!";
?? ??? ?return;
?? ?}
?? ?sprintf(buf1, "子進程返回的數據為 %s!\n", buf);
?? ?return;
}
子進程寫信息:
void WriteMsg()
{
?? ?DWORD dwWrite;
?? ?if (!WriteFile(hWrite, buf1, strlen(buf1) + 1, &dwWrite, NULL))
?? ?{
?? ??? ?cout << "寫入數據失敗!";
?? ??? ?return;
?? ?}
?
}
子進程的主函數:
int main(int argc, char* argv[])
{
?? ?hRead = GetStdHandle(STD_INPUT_HANDLE);//用于從一個特定的標準設備(標準輸入、標準輸出或標準錯誤)中取得一個句柄(用來標識不同設備的數值)
?? ?hWrite = GetStdHandle(STD_OUTPUT_HANDLE);
?? ?ReadMsg();
?? ?Sleep(200);
?? ?WriteMsg();
?? ?return 0;
}
---------------------?
原文:https://blog.csdn.net/qq_15029743/article/details/79492645?
?
總結
以上是生活随笔為你收集整理的C++匿名管道详解及简单案例(基于VS2013)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公司技术管理角度看C++游戏程序员发展
- 下一篇: 周鸿祎,高司令