日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

进程通信之二 管道技术第二篇 匿名管道

發(fā)布時(shí)間:2025/6/17 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程通信之二 管道技术第二篇 匿名管道 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上一篇《進(jìn)程通信之二 管道技術(shù)第一篇 輸入輸出的重定向》示范了增加若干程序代碼來(lái)完成程序輸入輸出的重定向,并提出了如果沒(méi)有程序源代碼,只有程序文件如何來(lái)完成重定向。本篇就介紹如何使用匿名管道來(lái)完成這一任務(wù)。

?

計(jì)算機(jī)中管道pipe類似于現(xiàn)實(shí)世界中的水管道,在一端放入水流,另一端就會(huì)流出來(lái)。在計(jì)算機(jī)機(jī)中水流自然被數(shù)據(jù)流所代替了。計(jì)算機(jī)中管道分為匿名管道和命名管道,本篇將主要介紹用匿名管道來(lái)完成這一重定向輸出任務(wù),命名管道就留給下一篇來(lái)介紹了。

先來(lái)看看如何創(chuàng)建和使用匿名管道。

?

第一個(gè) CreatePipe

函數(shù)功能:創(chuàng)建管道

函數(shù)原型:

BOOLWINAPICreatePipe(

? PHANDLEhReadPipe,

? PHANDLEhWritePipe,

? LPSECURITY_ATTRIBUTESlpPipeAttributes,

? DWORDnSize

);

函數(shù)說(shuō)明:

第一個(gè)參數(shù)返回新創(chuàng)建的管道的讀取端句柄。

第二個(gè)參數(shù)返回新創(chuàng)建的管道的寫(xiě)入端句柄。

注意不能在管道的讀取端寫(xiě)入數(shù)據(jù)也不能在寫(xiě)入端讀取數(shù)據(jù)。

第三個(gè)參數(shù)表示管道的安全屬性,通常可以作如下設(shè)置:

?????? SECURITY_ATTRIBUTES sa;?

?????? sa.nLength???????????? = sizeof(SECURITY_ATTRIBUTES);

?????? sa.lpSecurityDescriptor? ?= NULL;

?????? sa.bInheritHandle?????? = TRUE;

第四個(gè)參數(shù)表示管道的緩沖區(qū)容量,為0表示使用默認(rèn)大小。

函數(shù)執(zhí)行成功返回TRUE,否則返回FALSE

?

第二個(gè) ReadFile

函數(shù)功能:從管道中讀取數(shù)據(jù)

函數(shù)原型:

BOOLReadFile(

? HANDLEhFile,

? LPVOIDlpBuffer,

? DWORDnNumberOfBytesToRead,

? LPDWORDlpNumberOfBytesRead,

? LPOVERLAPPEDlpOverlapped

);

函數(shù)說(shuō)明:

第一個(gè)參數(shù)為句柄,可以是創(chuàng)建文件函數(shù)CreateFile()的返回值也可以是管道。

第二個(gè)參數(shù)是一個(gè)指向緩沖區(qū)的指針,函數(shù)將讀取的數(shù)據(jù)寫(xiě)入該緩沖區(qū)。

第三個(gè)參數(shù)的表達(dá)非常好,光從名字上就可以知道這是用來(lái)指定讀取的字節(jié)數(shù)。

第四個(gè)參數(shù)將返回實(shí)際讀取到的字節(jié)數(shù)。

第五個(gè)參數(shù)是用于異步操作方面,一般傳入NULL即可。

?

第三個(gè) WriteFile

函數(shù)功能:向管道寫(xiě)入數(shù)據(jù)

函數(shù)原型:

BOOLWriteFile(

? HANDLEhFile,

? LPCVOIDlpBuffer,

? DWORDnNumberOfBytesToWrite,

? LPDWORDlpNumberOfBytesWritten,

? LPOVERLAPPEDlpOverlapped

);

函數(shù)說(shuō)明:

第一個(gè)參數(shù)為句柄,可以是創(chuàng)建文件函數(shù)CreateFile()的返回值也可以是管道。

第二個(gè)參數(shù)是一個(gè)指針,該指針指向待寫(xiě)入管道的數(shù)據(jù)。

第三個(gè)參數(shù)表示要寫(xiě)入的字節(jié)數(shù)。

第四個(gè)參數(shù)將返回實(shí)際寫(xiě)入管道的字節(jié)數(shù)。

第五個(gè)參數(shù)是用于異步操作方面,一般傳入NULL即可。

?

第四個(gè)CloseHandle

函數(shù)功能:關(guān)閉管道的一端

函數(shù)原型:BOOLCloseHandle(HANDLEhObject);

函數(shù)說(shuō)明:當(dāng)讀取和寫(xiě)入端都關(guān)閉后,系統(tǒng)會(huì)關(guān)閉管道并回收資源。

?

從后面三個(gè)函數(shù)可以看出,向管道中讀取和寫(xiě)入數(shù)據(jù)就和向文件中讀取和寫(xiě)入數(shù)據(jù)是一樣的(事實(shí)上管道也是一種特殊的文件——內(nèi)存映射文件)。

?

使用管道要注意的一個(gè)地方是:讀取和寫(xiě)入數(shù)據(jù)時(shí),一定要注意順序,MSDN上說(shuō),如果管道中沒(méi)有數(shù)據(jù),調(diào)用ReadFile()會(huì)造成阻塞,直到有其它線程將數(shù)據(jù)寫(xiě)入管道。同樣,當(dāng)有線程正在管道中讀取數(shù)據(jù)時(shí),其它試圖將數(shù)據(jù)寫(xiě)入管道的的線程也會(huì)被阻塞。

?

因此對(duì)上一篇的示例程序進(jìn)行重定向時(shí),可以先創(chuàng)建二個(gè)管道,一個(gè)用來(lái)存放輸入數(shù)據(jù),稱為數(shù)據(jù)輸入管道,另一個(gè)用來(lái)存放輸出數(shù)據(jù),稱為數(shù)據(jù)輸出管道。然后從輸入文件中讀取數(shù)據(jù)并寫(xiě)入數(shù)據(jù)輸入管道。再啟動(dòng)示例程序作為子進(jìn)程,子進(jìn)程的輸入輸出已經(jīng)改成從數(shù)據(jù)輸入管道中讀取和輸出到數(shù)據(jù)輸出管道。子進(jìn)程運(yùn)行結(jié)束后,從數(shù)據(jù)輸出管道中將數(shù)據(jù)寫(xiě)入到輸出文件即可。整個(gè)流程圖如下所示:

下面給出使用管道的示例代碼:

//用管道來(lái)完成子進(jìn)程的重定向。 //流程如下: // infile.txt -> Input管道 -> 標(biāo)準(zhǔn)程序.exe -> Output管道 -> outfile.txt #include <windows.h> #include <stdio.h> int main() {printf(" 使用管道來(lái)重定向子進(jìn)程的輸入輸出\n"); printf(" --by MoreWindows( http://blog.csdn.net/MoreWindows )--\n\n"); char sz[3][50] = {"示例程序.exe", "infile.txt", "outfile.txt"};HANDLE hPipeInputRead, hPipeInputWrite, hPipeOutputRead, hPipeOutputWrite;//創(chuàng)建兩個(gè)管道SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor = NULL;sa.bInheritHandle = TRUE;//數(shù)據(jù)輸入管道CreatePipe(&hPipeInputRead, &hPipeInputWrite, &sa, 0);//數(shù)據(jù)輸出管道CreatePipe(&hPipeOutputRead, &hPipeOutputWrite, &sa, 0);printf("創(chuàng)建數(shù)據(jù)輸入管道和數(shù)據(jù)輸出管道完畢\n");//從文件中讀取數(shù)據(jù),寫(xiě)入管道ReadFile中.const int BUFSIZE = 4096;CHAR chBuf[BUFSIZE] = {0}; DWORD dwRead, dwWritten;BOOL fSuccess;HANDLE hInputFile = CreateFile(sz[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);while (true) {//從文件中讀取數(shù)據(jù)fSuccess = ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL);if (!fSuccess || dwRead == 0)break; //將數(shù)據(jù)寫(xiě)入管道fSuccess = WriteFile(hPipeInputWrite, chBuf, dwRead, &dwWritten, NULL);if (!fSuccess) break; } //關(guān)閉輸入數(shù)據(jù)管道CloseHandle(hInputFile);hInputFile = NULL;CloseHandle(hPipeInputWrite);hPipeInputWrite = NULL;printf("已經(jīng)從文件中讀取數(shù)據(jù)并寫(xiě)入數(shù)據(jù)輸入管道\n");printf("啟動(dòng)示例程序并重定向到管道中\(zhòng)n....\n");//啟動(dòng)示例程序作為子進(jìn)程STARTUPINFO si;si.cb = sizeof(STARTUPINFO);GetStartupInfo(&si); si.hStdInput = hPipeInputRead; //輸入由標(biāo)準(zhǔn)輸入 -> 從管道中讀取si.hStdOutput = hPipeOutputWrite; //輸出由標(biāo)準(zhǔn)輸出 -> 輸出到管道si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; CreateProcess( sz[0], NULL, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi);WaitForSingleObject(pi.hProcess, INFINITE);//關(guān)閉輸入數(shù)據(jù)管道CloseHandle(hPipeInputRead);hPipeInputRead = NULL;CloseHandle(hPipeOutputWrite);hPipeOutputWrite = NULL;printf("示例程序完成處理,現(xiàn)在將數(shù)據(jù)輸出管道中的數(shù)據(jù)寫(xiě)入文件\n");//將輸出數(shù)據(jù)管道中的數(shù)據(jù)寫(xiě)入到文件中HANDLE hOutputFile = CreateFile(sz[2], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); while (true){ //從管道中讀取fSuccess = ReadFile(hPipeOutputRead, chBuf, BUFSIZE, &dwRead, NULL);if( !fSuccess || dwRead == 0) break; //寫(xiě)入輸出文件fSuccess = WriteFile(hOutputFile, chBuf, dwRead, &dwWritten, NULL);if (!fSuccess) break; } //關(guān)閉輸出數(shù)據(jù)管道CloseHandle(hOutputFile);hOutputFile = NULL;CloseHandle(hPipeOutputRead);hPipeOutputRead = NULL;printf("數(shù)據(jù)輸出管道中的數(shù)據(jù)寫(xiě)入文件完畢\n");return 0; }

運(yùn)行結(jié)果如下圖:

結(jié)果完全正確,說(shuō)明我們的程序已經(jīng)完成了啟動(dòng)其它程序并對(duì)它進(jìn)行重定向這一功能。

?

對(duì)匿名管道總結(jié)一下:匿名管道有讀取端和寫(xiě)入端。匿名管道創(chuàng)建(CreatePipe)后就可以像讀寫(xiě)文件一樣的對(duì)管道中的數(shù)據(jù)讀寫(xiě)(ReadFileWriteFile),但要注意讀寫(xiě)順序。匿名管道在關(guān)閉兩端后會(huì)由系統(tǒng)銷毀并回收資源。

?

匿名管道的使用比較常見(jiàn),下面是二個(gè)安裝程序的截圖。

QQ游戲的安裝過(guò)程截圖:

五筆編碼及時(shí)查的安裝過(guò)程截圖:

對(duì)比下這二個(gè)截圖,顯示的內(nèi)容都差不多,都是解壓縮文件并移動(dòng)到指定地方。唯一不同的是一個(gè)是控制臺(tái)界面,另一個(gè)是圖形界面。聯(lián)想上面的程序,不難得知QQ游戲的安裝實(shí)際也是使用管道將一個(gè)控制臺(tái)程序的輸出內(nèi)容顯示到圖形界面,這樣既美觀又便于維護(hù)。

?

下一篇《進(jìn)程通信之二 管道技術(shù)第三篇 命名管道》將介紹命名管道的使用,歡迎參閱。

?

注:不知道程序代碼的情況下還可以使用批處理來(lái)完成。批處理使用><來(lái)重定向,>為輸出到文件,如果文件不存在就創(chuàng)建,已存在就清空原文件后再寫(xiě)入,<為從文件讀取。批處理文件的內(nèi)容可以這樣寫(xiě):

@echo off

<infile.txt 標(biāo)準(zhǔn)程序.exe >outfile.txt

也可以這樣寫(xiě):

@echo off

標(biāo)準(zhǔn)程序.exe <infile.txt >outfile.txt

批處理重定向的內(nèi)部實(shí)現(xiàn)原理當(dāng)然也是使用匿名管道。

?

轉(zhuǎn)載請(qǐng)標(biāo)明出處,原文地址:http://blog.csdn.net/morewindows/article/details/7390441

如果覺(jué)得本文對(duì)您有幫助,請(qǐng)點(diǎn)擊支持一下,您的支持是我寫(xiě)作最大的動(dòng)力,謝謝。

?

轉(zhuǎn)載于:https://www.cnblogs.com/long12365/p/9731284.html

總結(jié)

以上是生活随笔為你收集整理的进程通信之二 管道技术第二篇 匿名管道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。