匿名管道用於進程之間通信,且僅限於本地父子進程之間通信,結構簡單,類似於一根非水平狀態的水管,一端進水另一端出水(單工)。相對於命名管道,其占用小實現簡單,在特定情況下,比如實現兩圍棋引擎本地對戰可以使用匿名管道。
基本介紹
- 中文名:匿名管道
- 外文名:Anonymous pipes
簡介
管道特徵
匿名管道的特徵:
①只提供單向通信,也就是說,兩個進程都能訪問這個檔案,假設進程1往檔案內寫東西,那么進程2 就只能讀取檔案的內容。
②只能用於具有血緣關係的進程間通信,通常用於父子進程建通信
③管道是基於位元組流來通信的
④依賴於檔案系統,它的生命周期隨進程的結束結束(隨進程)
⑤其本身自帶同步互斥效果
匿名管道的使用
Windows作業系統
// 父進程#include <windows.h>int main(){ STARTUPINFO si; PROCESS_INFORMATION pi; char ReadBuf[100]; DWORD ReadNum; HANDLE hRead; // 管道讀句柄 HANDLE hWrite; // 管道寫句柄 BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 創建匿名管道 if (bRet == TRUE) printf("成功創建匿名管道!\n"); else printf("創建匿名管道失敗,錯誤代碼:%d\n", GetLastError()); HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);// 得到本進程的當前標準輸出 SetStdHandle(STD_OUTPUT_HANDLE, hWrite);// 設定標準輸出到匿名管道 GetStartupInfo(&si); // 獲取本進程的STARTUPINFO結構信息 bRet = CreateProcess( // 創建子進程 NULL, // No module name (use command line) (LPSTR)(LPCSTR)"Client.exe", // Command lineNULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure if (bRet == TRUE) printf("成功創建子進程!\n"); else printf("創建子進程失敗,錯誤代碼:%d\n", GetLastError()); SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢複本進程的標準輸出 CloseHandle(hWrite); // 關閉寫句柄 while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))// 讀管道直至管道關閉 { ReadBuf[ReadNum] = '\0'; printf("從管道[%s]讀取%d位元組數據\n", ReadBuf, ReadNum); } if (GetLastError() == ERROR_BROKEN_PIPE) // 輸出信息 printf("管道被子進程關閉\n"); else printf("讀數據錯誤,錯誤代碼:%d\n", GetLastError()); return 0;}
//子進程的標準輸出實際上已經重定向到匿名管道寫端#include <stdio.h>int main(int argc, char* argv[]){ for (int i = 0; i < 100; i++) // 傳送一些數據到標準輸出和標準錯誤 { printf("i = %d\n", i); // 列印提示 cout << "標準輸出:" << i << endl; // 列印到標準輸出 cerr << "標準錯誤:" << i << endl; // 列印到標準錯誤 } return 0;}
- 如果所有指向管道寫端的檔案描述符都關閉了,而仍然有進程從管道的讀端讀數據,那么檔案內的所有內容被讀完後再次read就會返回0,就像讀到檔案結尾。
- 如果有指向管道寫端的檔案描述符沒有關閉(管道寫段的引用計數大於0),而持有管道寫端的進程沒有向管道內寫入數據,假如這時有進程從管道讀端讀數據,那么讀完管道內剩餘的數據後就會阻塞等待,直到有數據可讀才讀取數據並返回。
- 如果所有指向管道讀端的檔案描述符都關閉,此時有進程通過寫端檔案描述符向管道內寫數據時,則該進程就會收到SIGPIPE信號,並異常終止。
- 如果有指向管道讀端的檔案描述符沒有關閉(管道讀端的引用計數大於0),而持有管道讀端的進程沒有從管道內讀數據,假如此時有進程通過管道寫段寫數據,那么管道被寫滿後就會被阻塞,直到管道內有空位置後才寫入數據並返回。