匿名管道
一個單向,未命名的管道,通常用來在一個父程序和一個子程序間傳輸資料。隻能實作本地機器上兩個程序間的通信,而不能實作跨網絡的通信。
BOOL CreatePipe(
PHANDLE hReadPipe, // read handle
PHANDLE hWritePipe, // write handle
LPSECURITY_ATTRIBUTES lpPipeAttributes, // security attributes
DWORD nSize // pipe size
);
CreateProcess 建立程序
建立父程序:
a. CreatePipe:其中第三個參數代表安全屬性結構體SECURITY_ATTRIBUTES的指針,在前幾章的運用中,都是運用了NULL,代表傳回的安全句柄不可以被子程序所繼承。但在本運用中,涉及到的是匿名管道。匿名管道就是父子程序之間的通信,是以結構體必須設定相應的值。子程序要想獲得匿名管道的讀寫句柄,隻能從父程序繼承而來。一旦子程序有了繼承而來的讀寫句柄,就可以和父程序進行通信了。對于機構體SECURITY_ATTRIBUTES,最重要的是第三個參數bInheritHandle,表示Specifies whether the returned handle is inherited when a new process is created. If this member is TRUE, the new process inherits the handle.
b. CreateProcess:如果建立管道成功,則建立子程序,并将管道的讀寫句柄傳遞給子程序。
1.MFC單文檔程式菜單中增加建立管道,讀取資料,寫入資料三項
2.View類中增加成員變量
3. CreateProcess
倒數第三個參數 [in] Pointer to a STARTUPINFO structure that specifies how the main window for the new process should appear 指向STARTUPINFO結構體的一個指針,用來指定新的程序它的主視窗如何出現
最後一個參數指向PROCESS_INFORMATION結構體的一個指針的傳回值,用來接收新的程序的辨別資訊
PROCESS_INFORMATION
The PROCESS_INFORMATION structure is filled in by the CreateProcess function with information
about a newly created process and its primary thread.
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
Members
hProcess //新建立程序的句柄
A handle to the newly created process. The handle is used to specify the process in all
functions that perform operations on the process object.
hThread //新建立程序主線程的句柄
A handle to the primary thread of the newly created process. The handle is used to specify
the thread in all functions that perform operations on the thread object.
dwProcessId //全局程序辨別符,如果程序結束作業系統可能會将辨別配置設定給其他程序,我們調用辨別的時候要確定程序在運作
A global process identifier that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated.
dwThreadId //全局線程辨別符
A global thread identifiers that can be used to identify a thread. The value is valid from the
time the thread is created until the time the thread is terminated.
建立匿名管道具體代碼:
SECURITY_ATTRIBUTES sa;
//總共就三個參數
sa.bInheritHandle=TRUE; //表示可被子程序所繼承
sa.lpSecurityDescriptor=NULL; //安全描述符号一般都設定成NULL,即預設描述符
sa.nLength=sizeof(SECURITY_ATTRIBUTES); //管道長度
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
MessageBox("建立匿名函數失敗!");
return;
}
//管道建立成功後,接着建立子程序,并将讀寫句柄傳遞給子程序
STARTUPINFO sui;
PROCESS_INFORMATION pi;
//調用ZeroMemory方法将該結構體中的所有成員都置為0,這是因為這個結構體的成員很多,如果開始的時候沒有置為0的話,那它的值是随機的,将這樣的結構體傳給CreateProcess,可能會影響到執行的結果。
ZeroMemory(&sui,sizeof(STARTUPINFO));
sui.cb=sizeof(STARTUPINFO); //設定結構體的大小
sui.dwFlags=STARTF_USESTDHANDLES; //該辨別表示标準輸入句柄,标準輸出句柄和錯誤句柄是有用的
sui.hStdInput=hRead; //将子程序的輸入句柄設定成父程序的讀句柄
sui.hStdOutput=hWrite; //将子程序的輸出句柄設定成父程序的寫句柄
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE); //得到标準錯誤句柄,是父程序的錯誤句柄,該行代碼在本程式中沒有實際的用途意義
//因為是匿名管道,是沒有名稱的管道,隻有通過CreateProcess由上而下的傳遞管道操作句柄。
if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,
TRUE,0,NULL,NULL,&sui,π))
MessageBox("建立子程序失敗!");
CloseHandle(hRead);
CloseHandle(hWrite);
//避免在析構函數中再次關閉,析構函數采用:
//if(hRead) CloseHandle(hRead)
hRead=NULL;
hWrite=NULL;
else
//建立一個新的程序的時候,系統會建立一個程序核心對象和一個線程核心對象,核心對象都有一個使用基數,初始調用的時候,都設定為1。在CreateProcess傳回之前,該函數打開程序和線程的核心對象,并将程序相關的句柄放置到結構體PROCESS_INFORMATION的hProcess和hThread中,當Process在内部打開這些對象的時候,使得每個對象的使用基數增加到2了。如果在父程序中不需要使用這兩個句柄,就将這個句柄進行關閉,使得使用基數減1。當子程序終結的時候,系統會在将使用基數減1,使得子程序的程序核心對象和線程核心對象的使用基數變為0,這樣核心對象就可以被釋放了。
CloseHandle(pi.hProcess); //關閉子程序的句柄
CloseHandle(pi.hThread); //關閉子程序中主線程的句柄
}
父程序寫匿名管道:
char *buf="hello world";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
MessageBox("匿名管道寫入資料失敗!");
父程序讀匿名管道:
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
MessageBox("匿名管道讀取資料失敗!");
MessageBox(buf);
建立子程序程式:
可以将擷取父程序的匿名管道的讀寫句柄操作放在CView類的OnInitialUpdate方法中實作,該方法是在CView完全構造後調用的第一個方法。代碼如下:
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
子程序的讀寫匿名管道的代碼和父程序的一樣,這裡不再累述。
為了讓子程序從衆多繼承的句柄中區分出管道的讀、寫句柄,就必須将子程序的特殊句柄設定為管道的讀寫句柄。