小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

進(jìn)程間通信---1.匿名管道

 semo_zhang 2013-06-08
1、匿名管道
實(shí)現(xiàn)進(jìn)程間通信,是各個(gè)進(jìn)程間互相交流的橋梁。
本節(jié)所講述的匿名管道有以下幾個(gè)主要的性質(zhì):
1、匿名管道只能實(shí)現(xiàn)本地進(jìn)程間的通信,跨網(wǎng)絡(luò)的進(jìn)程間的通信無(wú)法通過(guò)匿名管道實(shí)現(xiàn)的。
2、匿名管道采用半雙工的方式通信,且通信的進(jìn)程間是有血緣關(guān)系的,及父子關(guān)系或者兄弟關(guān)系進(jìn)程,由此可知并不是本地計(jì)算機(jī)上任意兩個(gè)進(jìn)程就能通過(guò)匿名管道進(jìn)行通信。
3、匿名管道有個(gè)重要的功能就是可以通過(guò)匿名管道的來(lái)實(shí)現(xiàn)子進(jìn)程輸出的的重定向。
下面是一個(gè)小小的實(shí)例,表現(xiàn)了重定向在具體模型中怎么用:

比如我現(xiàn)在建立一個(gè) Win32 的 Console 程序,然后在其中使用如下代碼來(lái)輸出一些信息:

#include <iostream>
using namespace std;
 
int main(int argc, char * argv)
{
    cout<<"Zachary  XiaoZhen "<<endl<<endl;
    cout<<"Happy  New   Year"<<endl<<endl;
    
    system("pause");
}

那么在默認(rèn)下,編譯運(yùn)行上面的代碼時(shí),Windows 會(huì)彈出一個(gè)黑框框,并且在這個(gè)黑框框中顯示一些信息,

image

為什么一定要將輸出的信息顯示在這個(gè)黑框框中呢?有沒(méi)有辦法讓其顯示在我們自己定義的文本框中呢?

而后我們?cè)倏匆环貓D:

QQ截圖未命名

上面畫(huà)了很多紅線的這個(gè)區(qū)域中的信息來(lái)自那里呢?為什么會(huì)在這個(gè)文本框中輸出呢?

其實(shí)這就可以通過(guò)匿名管道來(lái)實(shí)現(xiàn),

在卸載 QQ 游戲這幅截圖中呢,其實(shí)運(yùn)行了兩個(gè)進(jìn)程,

一個(gè)就是我們看到的這個(gè)輸出了圖形界面的進(jìn)程,我們稱之為卸載表象進(jìn)程(父進(jìn)程),

而另外一個(gè)用來(lái)執(zhí)行真正意義上的卸載的進(jìn)程我們稱之為卸載實(shí)質(zhì)進(jìn)程(子進(jìn)程)。

其實(shí)該卸載表象進(jìn)程在其執(zhí)行過(guò)程中創(chuàng)建了卸載實(shí)質(zhì)進(jìn)程來(lái)執(zhí)行真正的卸載操作,

而后,卸載實(shí)質(zhì)進(jìn)程會(huì)輸出上面用紅色矩形標(biāo)記的區(qū)域中的信息,

如果我們使用默認(rèn)的輸出的話,卸載實(shí)質(zhì)進(jìn)程會(huì)將上面紅色區(qū)域標(biāo)記中的信息輸出到默認(rèn)的黑框框中,

但是我們可以使用匿名管道來(lái)更改卸載實(shí)質(zhì)進(jìn)程的輸出,

讓其將輸出數(shù)據(jù)輸入到匿名管道中,而后卸去除格式載表象進(jìn)程從匿名管道中讀取到這些輸出數(shù)據(jù),

然后再將這些數(shù)據(jù)顯示到卸載表象進(jìn)程的文本框格式刷格式刷就可以了。

而上面的這種用來(lái)更改卸載實(shí)質(zhì)進(jìn)程的輸出的技術(shù)就稱之為輸出重定向。

當(dāng)然與之相對(duì)的還有輸入重定向的。

我們可以讓一個(gè)進(jìn)程的輸入來(lái)自于匿名管道,而不是我們?cè)诤诳蚩蛑休斎霐?shù)據(jù)。

上面的這個(gè)重定向不就是利用匿名管道實(shí)現(xiàn)的父進(jìn)程和子進(jìn)程之間的通信嘛。

             匿名管道相關(guān)函數(shù):

匿名管道的創(chuàng)建

BOOL WINAPI CreatePipe(
          __out   PHANDLE hReadPipe,
          __out   PHANDLE hWritePipe,
          __in    LPSECURITY_ATTRIBUTES lpPipeAttributes,
          __in    DWORD nSize );

參數(shù) hReadPipe 為輸出參數(shù),該句柄代表管道的讀取句柄。

參數(shù) hWritePipe 為輸出參數(shù),該句柄代表管道的寫(xiě)入句柄。

參數(shù) lpPipeAttributes 為一個(gè)輸入?yún)?shù),指向一個(gè) SECURITY_ATTRIBUTES 的結(jié)構(gòu)體指針,

其檢測(cè)返回的句柄是否能夠被子進(jìn)程繼承,如果此參數(shù)為 NULL ,則表明句柄不能被繼承,

在匿名管道中,由于匿名管道要在父子進(jìn)程之間進(jìn)行通信,

而子進(jìn)程如果想要獲得匿名管道的讀寫(xiě)句柄,則其只能通過(guò)從父進(jìn)程繼承獲得,

當(dāng)一個(gè)子進(jìn)程從其父進(jìn)程處繼承了匿名管道的讀寫(xiě)句柄以后,

子進(jìn)程和父進(jìn)程之間就可以通過(guò)這個(gè)匿名管道的讀寫(xiě)句柄進(jìn)行通信了。

所以在這里必須構(gòu)建一個(gè) SECURITY_ATTRIBUTES 的結(jié)構(gòu)體,

并且該結(jié)構(gòu)體的第三個(gè)結(jié)構(gòu)成員變量 bInheritHandle 參數(shù)必須設(shè)置為 TRUE ,

從而讓子進(jìn)程可以繼承父進(jìn)程所創(chuàng)建的匿名管道的讀寫(xiě)句柄。

typedef struct _SECURITY_ATTRIBUTES {
 
    DWORD nLength;
 
    LPVOID lpSecurityDescriptor;
 
    BOOL bInheritHandle;
 
} SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

參數(shù) nSize 用來(lái)指定緩沖區(qū)的大小,

如果此參數(shù)設(shè)置為 0 ,則表明系統(tǒng)將使用默認(rèn)的緩沖區(qū)大小。一般將該參數(shù)設(shè)置為 0 即可。

         

              

子進(jìn)程的創(chuàng)建

BOOL  CreateProcess( 
        LPCWSTR pszImageName,  LPCWSTR pszCmdLine, 
        LPSECURITY_ATTRIBUTES psaProcess, 
        LPSECURITY_ATTRIBUTES psaThread, 
        BOOL fInheritHandles,  DWORD fdwCreate, 
        LPVOID pvEnvironment,  LPWSTR pszCurDir, 
        LPSTARTUPINFOW psiStartInfo, 
        LPPROCESS_INFORMATION pProcInfo );

參數(shù) pszImageName 是一個(gè)指向 NULL 終止的字符串,用來(lái)指定可執(zhí)行程序的名稱。

參數(shù) pszCmdLine 用來(lái)指定傳遞給新進(jìn)程的命令行字符串,一般做法是在 pszImageName 中傳遞可執(zhí)行文件的名稱,

pszCmdLine 中傳遞命令行參數(shù)。

參數(shù) psaProcess 即代表當(dāng) CreateProcess 函數(shù)創(chuàng)建進(jìn)程時(shí),需要給進(jìn)程對(duì)象設(shè)置一個(gè)安全性。

參數(shù) psaThread 代表當(dāng) CreateProcess 函數(shù)創(chuàng)建新進(jìn)程后,需要給該進(jìn)程的主線程對(duì)象設(shè)置一個(gè)安全性。

參數(shù) fInheritHandles 用來(lái)指定父進(jìn)程隨后創(chuàng)建的子進(jìn)程是否能夠繼承父進(jìn)程的對(duì)象句柄,

如果該參數(shù)設(shè)置為 TRUE ,則父進(jìn)程的每一個(gè)可繼承的打開(kāi)句柄都將被子進(jìn)程所繼承,

繼承的句柄與原始的句柄擁有同樣的訪問(wèn)權(quán)。

在匿名管道的使用中,因?yàn)樽舆M(jìn)程需要使用父進(jìn)程中創(chuàng)建的匿名管道的讀寫(xiě)句柄,

所以應(yīng)該將這個(gè)參數(shù)設(shè)置為 TRUE ,從而可以讓子進(jìn)程繼承父進(jìn)程創(chuàng)建的匿名管道的讀寫(xiě)句柄。

參數(shù) fdwCreate 用來(lái)指定控件優(yōu)先級(jí)類(lèi)和進(jìn)程創(chuàng)建的附加標(biāo)記。

如果只是為了啟動(dòng)子進(jìn)程,則并不需要設(shè)置它創(chuàng)建的標(biāo)記,可以將此參數(shù)設(shè)置為 0,

對(duì)于這個(gè)參數(shù)的具體取值列表可以參考 MSDN 。

參數(shù) pvEnvironment 代表指向環(huán)境塊的指針,

如果該參數(shù)設(shè)置為 NULL ,則默認(rèn)將使用父進(jìn)程的環(huán)境。通常給該參數(shù)傳遞 NULL。

參數(shù) pszCurDir 用來(lái)指定子進(jìn)程當(dāng)前的路徑,

這個(gè)字符串必須是一個(gè)完整的路徑名,其包括驅(qū)動(dòng)器的標(biāo)識(shí)符,

如果此參數(shù)設(shè)置為 NULL ,那么新的子進(jìn)程將與父進(jìn)程擁有相同的驅(qū)動(dòng)器和目錄。

參數(shù) psiStartInfo 指向一個(gè) StartUpInfo 的結(jié)構(gòu)體的指針,用來(lái)指定新進(jìn)程的主窗口如何顯示。

typedef struct _STARTUPINFOA {
 
    DWORD cb;
 
    LPSTR lpReserved;
 
    LPSTR lpDesktop;
 
    LPSTR lpTitle;
 
    DWORD dwX;
 
    DWORD dwY;
 
    DWORD dwXSize;
 
    DWORD dwYSize;
 
    DWORD dwXCountChars;
 
    DWORD dwYCountChars;
 
    DWORD dwFillAttribute;
 
    DWORD dwFlags;
 
    WORD wShowWindow;
 
    WORD cbReserved2;
 
    LPBYTE lpReserved2;
 
    HANDLE hStdInput;
 
    HANDLE hStdOutput;
 
    HANDLE hStdError;
 
} STARTUPINFOA, *LPSTARTUPINFOA;

對(duì)于 dwFlags 參數(shù)來(lái)說(shuō),如果其設(shè)置為 STARTF_USESTDHANDLES ,

則將會(huì)使用該 STARTUPINFO 結(jié)構(gòu)體中的 hStdInput , hStdOutput hStdError 成員,

來(lái)設(shè)置新創(chuàng)建的進(jìn)程的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤句柄。

參數(shù) pProcInfo 為一個(gè)輸出參數(shù),

指向一個(gè) PROCESS_INFORMATION 結(jié)構(gòu)體的指針,用來(lái)接收關(guān)于新進(jìn)程的標(biāo)識(shí)信息。

typedef struct _PROCESS_INFORMATION 
{             
    HANDLE hProcess;             
    HANDLE hThread;             
    DWORD dwProcessId;              
    DWORD dwThreadId; 
 
}PROCESS_INFORMATION;

其中 hProcess hThread 分別用來(lái)標(biāo)識(shí)新創(chuàng)建的進(jìn)程句柄和新創(chuàng)建的進(jìn)程的主線程句柄。

dwProcessId dwThreadId 分別是全局進(jìn)程標(biāo)識(shí)符和全局線程標(biāo)識(shí)符。

前者可以用來(lái)標(biāo)識(shí)一個(gè)進(jìn)程,后者用來(lái)標(biāo)識(shí)一個(gè)線程。

        

示例:匿名管道實(shí)現(xiàn)父子進(jìn)程間通信

父進(jìn)程實(shí)現(xiàn):(簡(jiǎn)單 MFC 程序)

項(xiàng)目結(jié)構(gòu):

image

消息以及成員函數(shù)和成員變量的聲明:

public:
    //創(chuàng)建匿名管道
    afx_msg void OnBnClickedBtnCreatePipe();
    //寫(xiě)匿名管道
    afx_msg void OnBnClickedBtnWritePipe();
    //讀匿名管道
    afx_msg void OnBnClickedBtnReadPipe();
 
    //定義父進(jìn)程讀匿名管道的成員函數(shù)
    void ParentReadPipe(void);
    //定義父進(jìn)程寫(xiě)匿名管道的成員函數(shù)
    void ParentWritePipe(void);
    //創(chuàng)建 SECURITY_ATTRIBUTES 結(jié)構(gòu)的成員函數(shù)
    void CreateSecurityAttributes(PSECURITY_ATTRIBUTES pSa);
    //創(chuàng)建 STARTUPINFO 結(jié)構(gòu)的成員函數(shù)
    void CreateStartUpInfo(LPSTARTUPINFO lpStartUpInfo);
    //創(chuàng)建匿名管道的成員函數(shù)
    void CreateNoNamedPipe(void);
 
    //分別代表要從匿名管道中讀的數(shù)據(jù)和要寫(xiě)到匿名管道中的數(shù)據(jù)
    CString m_CStrReadPipe;
    CString m_CStrWritePipe;
 
    //保存創(chuàng)建匿名管道后所得到的對(duì)匿名管道的讀寫(xiě)句柄
    HANDLE hPipeRead;
    HANDLE hPipeWrite;
    
    //保證匿名管道只創(chuàng)建一次
    BOOL m_PipeIsCreated;

消息映射表定義:

const int        dataLength    = 100;
 
CNoNamedPipeParentDlg::CNoNamedPipeParentDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CNoNamedPipeParentDlg::IDD, pParent)
    , m_CStrReadPipe(_T(""))
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 
    m_PipeIsCreated = FALSE;
}
 
void CNoNamedPipeParentDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT_WRITE_PIPE, m_CStrWritePipe);
    DDX_Text(pDX, IDC_EDIT_READ_PIPE, m_CStrReadPipe);
}
 
BEGIN_MESSAGE_MAP(CNoNamedPipeParentDlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BTN_CREATE_PIPE, 
                &CNoNamedPipeParentDlg::OnBnClickedBtnCreatePipe)
    ON_BN_CLICKED(IDC_BTN_WRITE_PIPE, 
                &CNoNamedPipeParentDlg::OnBnClickedBtnWritePipe)
    ON_BN_CLICKED(IDC_BTN_READ_PIPE, 
                &CNoNamedPipeParentDlg::OnBnClickedBtnReadPipe)
END_MESSAGE_MAP()

消息處理函數(shù):

//創(chuàng)建匿名管道按鈕的消息處理函數(shù)
void CNoNamedPipeParentDlg::OnBnClickedBtnCreatePipe()
{
    if(m_PipeIsCreated == FALSE)
    {
        this->CreateNoNamedPipe();
    }
}
 
 
//寫(xiě)入數(shù)據(jù)到匿名管道中按鈕的消息處理函數(shù)
void CNoNamedPipeParentDlg::OnBnClickedBtnWritePipe()
{
    this->ParentWritePipe();
}
 
 
//從匿名管道中讀取數(shù)據(jù)按鈕的消息處理函數(shù)
void CNoNamedPipeParentDlg::OnBnClickedBtnReadPipe()
{
    this->ParentReadPipe();
}
 
 
//接收數(shù)據(jù)
void CNoNamedPipeParentDlg::ParentReadPipe(void)
{
    DWORD            dwRead;
    char *            pReadBuf;
    CString            cStrRecvData;
 
    pReadBuf = new char[dataLength];
    memset(pReadBuf, 0, dataLength);
 
    if(!ReadFile(hPipeRead, pReadBuf, dataLength, &dwRead, NULL))
    {
        MessageBox(TEXT("   從匿名管道接收數(shù)據(jù)失敗 ..."), 
            TEXT("提示"), MB_ICONERROR);
        return;
    }
 
    cStrRecvData = "   從匿名管道接收數(shù)據(jù)成功:    ";
    cStrRecvData += pReadBuf;
 
    this->m_CStrReadPipe.Empty();
 
    this->m_CStrReadPipe = pReadBuf;
    UpdateData(FALSE);
 
    MessageBox(cStrRecvData, TEXT("提示"), MB_ICONINFORMATION);
}
 
 
//發(fā)送數(shù)據(jù)
void CNoNamedPipeParentDlg::ParentWritePipe(void)
{
    UpdateData();
 
    if(!this->m_CStrWritePipe.IsEmpty())
    {
        char *            pSendData;
        DWORD            dwWrite;
        CString            cStrSendData;
 
        //在這里需要將 Unicode 字符集轉(zhuǎn)換為 ASCII 字符集
        pSendData = new char[this->m_CStrWritePipe.GetLength() + 1];
        memset(pSendData, 0, this->m_CStrWritePipe.GetLength() + 1);
        for(int i=0;i<this->m_CStrWritePipe.GetLength();i++)
        {
            pSendData[i] = (char)this->m_CStrWritePipe.GetAt(i);
        }
 
        if(!WriteFile(hPipeWrite, pSendData, 
            this->m_CStrWritePipe.GetLength() + 1, &dwWrite, NULL))
        {
            MessageBox(TEXT("   給匿名管道發(fā)送數(shù)據(jù)失敗 ..."), 
                TEXT("提示"), MB_ICONERROR);
            return;
        }
 
        cStrSendData = "   給匿名管道發(fā)送數(shù)據(jù)成功:    ";
        cStrSendData += this->m_CStrWritePipe;
 
        this->m_CStrWritePipe.Empty();
        UpdateData(FALSE);
 
        MessageBox(cStrSendData, TEXT("提示"), MB_ICONINFORMATION);
    }
    else
    {
        MessageBox(TEXT("   請(qǐng)先輸入要發(fā)送給匿名管道的數(shù)據(jù) ..."), 
            TEXT("提示"), MB_ICONERROR);
    }
}
 
 
//創(chuàng)建 SECURITY_ATTRIBUTES 結(jié)構(gòu)
void CNoNamedPipeParentDlg::CreateSecurityAttributes(PSECURITY_ATTRIBUTES pSa)
{
    //這里必須將 bInheritHandle 設(shè)置為 TRUE,
    //從而使得子進(jìn)程可以繼承父進(jìn)程創(chuàng)建的匿名管道的句柄
    pSa->bInheritHandle = TRUE;
    pSa->lpSecurityDescriptor = NULL;
    pSa->nLength = sizeof(SECURITY_ATTRIBUTES);
}
 
 
//用來(lái)初始化新進(jìn)程的 STARTUPINFO 成員
void CNoNamedPipeParentDlg::CreateStartUpInfo(LPSTARTUPINFO lpStartUpInfo)
{
    memset(lpStartUpInfo, 0, sizeof(STARTUPINFO));
 
    lpStartUpInfo->cb = sizeof(STARTUPINFO);
    lpStartUpInfo->dwFlags = STARTF_USESTDHANDLES;
 
    //子進(jìn)程的標(biāo)準(zhǔn)輸入句柄為父進(jìn)程管道的讀數(shù)據(jù)句柄
    lpStartUpInfo->hStdInput = hPipeRead;
 
    //子進(jìn)程的標(biāo)準(zhǔn)輸出句柄為父進(jìn)程管道的寫(xiě)數(shù)據(jù)句柄
    lpStartUpInfo->hStdOutput = hPipeWrite;
 
    //子進(jìn)程的標(biāo)準(zhǔn)錯(cuò)誤處理句柄和父進(jìn)程的標(biāo)準(zhǔn)錯(cuò)誤處理句柄一致
    lpStartUpInfo->hStdError = GetStdHandle(STD_ERROR_HANDLE);
}
 
 
//創(chuàng)建匿名管道
void CNoNamedPipeParentDlg::CreateNoNamedPipe(void)
{
    SECURITY_ATTRIBUTES                sa;
    PROCESS_INFORMATION                processInfo;
    STARTUPINFO                        startUpInfo;
 
    CreateSecurityAttributes(&sa);
    if(!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0))
    {
        MessageBox(TEXT("   創(chuàng)建匿名管道失敗 ..."), 
            TEXT("提示"), MB_ICONERROR);
        return;
    }
 
    CreateStartUpInfo(&startUpInfo);
    if(!CreateProcess(TEXT("NoNamedPipeChild.exe"), 
        NULL, NULL, NULL, TRUE, 
        CREATE_NEW_CONSOLE, NULL, NULL, 
        &startUpInfo, &processInfo))
    {
        CloseHandle(hPipeRead);
        CloseHandle(hPipeWrite);
 
        hPipeWrite = NULL;
        hPipeRead = NULL;
 
        MessageBox(TEXT("   創(chuàng)建子進(jìn)程失敗 ..."), 
            TEXT("提示"), MB_ICONERROR);
        return;
    }
    else
    {
        m_PipeIsCreated = TRUE;
 
        //對(duì)于 processInfo.hProcess 和 processInfo.hThread 
        //這兩個(gè)句柄不需要使用,所以釋放資源
        CloseHandle(processInfo.hProcess);
        CloseHandle(processInfo.hThread);
    }
}

子進(jìn)程實(shí)現(xiàn):(簡(jiǎn)單 MFC 程序)

項(xiàng)目結(jié)構(gòu):

image

消息以及成員函數(shù)和成員變量的聲明:

// 實(shí)現(xiàn)
protected:
    HICON m_hIcon;
 
    // 生成的消息映射函數(shù)
    virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedBtnWritePipe();
    afx_msg void OnBnClickedBtnReadPipe();
 
    //保存從父進(jìn)程得到針對(duì)于匿名管道的讀寫(xiě)句柄
    HANDLE hPipeRead;
    HANDLE hPipeWrite;
 
    //分別代表要從匿名管道中讀的數(shù)據(jù)和要寫(xiě)到匿名管道中的數(shù)據(jù)
    CString m_CStrWritePipe;
    CString m_CStrReadPipe;
 
    //子進(jìn)程讀取匿名管道
    void ChildReadPipe(void);
    //子進(jìn)程寫(xiě)匿名管道
    void ChildWritePipe(void);
    //子進(jìn)程獲取從父進(jìn)程處繼承得到的關(guān)于匿名管道的讀寫(xiě)句柄
    void GetReadWriteHandleFromParent(void);
 
    //只需要獲取一次匿名管道的讀寫(xiě)句柄即可
    BOOL m_IsGettedParentHandle;

消息映射表定義:

const int        dataLength    = 100;
 
CNoNamedPipeChildDlg::CNoNamedPipeChildDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CNoNamedPipeChildDlg::IDD, pParent)
    , m_CStrWritePipe(_T(""))
    , m_CStrReadPipe(_T(""))
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 
    this->m_IsGettedParentHandle = FALSE;
}
 
void CNoNamedPipeChildDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT_WRITE_PIPE, m_CStrWritePipe);
    DDX_Text(pDX, IDC_EDIT_READ_PIPE, m_CStrReadPipe);
}
 
BEGIN_MESSAGE_MAP(CNoNamedPipeChildDlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(ID_BTN_WRITE_PIPE, 
            &CNoNamedPipeChildDlg::OnBnClickedBtnWritePipe)
    ON_BN_CLICKED(ID_BTN_READ_PIPE, 
            &CNoNamedPipeChildDlg::OnBnClickedBtnReadPipe)
END_MESSAGE_MAP()

消息處理函數(shù):

//往匿名管道中寫(xiě)入數(shù)據(jù)按鈕的消息處理函數(shù)
void CNoNamedPipeChildDlg::OnBnClickedBtnWritePipe()
{
    //如果子進(jìn)程還沒(méi)有獲得對(duì)匿名管道的讀寫(xiě)句柄的話需要先獲取句柄
    this->GetReadWriteHandleFromParent();
 
    ChildWritePipe();
}
 
 
//從匿名管道中讀取數(shù)據(jù)按鈕的消息處理函數(shù)
void CNoNamedPipeChildDlg::OnBnClickedBtnReadPipe()
{
    //如果子進(jìn)程還沒(méi)有獲得對(duì)匿名管道的讀寫(xiě)句柄的話需要先獲取句柄
    this->GetReadWriteHandleFromParent();
 
    ChildReadPipe();
}
 
//從匿名管道讀取數(shù)據(jù)成員函數(shù)
void CNoNamedPipeChildDlg::ChildReadPipe(void)
{
    DWORD            dwRead;
    char *            pReadBuf;
    CString            cStrRecvData;
 
    pReadBuf = new char[dataLength];
    memset(pReadBuf, 0, dataLength);
 
    //讀取數(shù)據(jù)
    if(!ReadFile(hPipeRead, pReadBuf, dataLength, &dwRead, NULL))
    {
        MessageBox(TEXT("   從匿名管道接收數(shù)據(jù)失敗 ..."), 
            TEXT("提示"), MB_ICONERROR);
        return;
    }
 
    cStrRecvData = "   從匿名管道接收數(shù)據(jù)成功:    ";
    cStrRecvData += pReadBuf;
 
    this->m_CStrReadPipe.Empty();
    this->m_CStrReadPipe = pReadBuf;
    UpdateData(FALSE);
 
    MessageBox(cStrRecvData, TEXT("提示"), MB_ICONINFORMATION);
}
 
//往匿名管道中寫(xiě)入數(shù)據(jù)
void CNoNamedPipeChildDlg::ChildWritePipe(void)
{
    UpdateData();
 
    if(!this->m_CStrWritePipe.IsEmpty())
    {
        char *                pSendData;
        DWORD                dwWrite;
        CString                cStrSendData;
 
        //在這里需要將 Unicode 字符集轉(zhuǎn)換為 ASCII 字符集
        pSendData = new char[this->m_CStrWritePipe.GetLength() + 1];
        memset(pSendData, 0, this->m_CStrWritePipe.GetLength() + 1);
        for(int i=0;i<this->m_CStrWritePipe.GetLength();i++)
        {
            pSendData[i] = (char)this->m_CStrWritePipe.GetAt(i);
        }
 
        //寫(xiě)入數(shù)據(jù)
        if(!WriteFile(hPipeWrite, pSendData, 
            this->m_CStrWritePipe.GetLength(), &dwWrite, NULL))
        {
            MessageBox(TEXT("   給匿名管道發(fā)送數(shù)據(jù)失敗 ..."), 
                TEXT("提示"), MB_ICONERROR);
            return;
        }
 
        cStrSendData = "給匿名管道發(fā)送數(shù)據(jù)成功:    ";
        cStrSendData += this->m_CStrWritePipe;
 
        this->m_CStrWritePipe.Empty();
        UpdateData(FALSE);
 
        MessageBox(cStrSendData, TEXT("提示"), MB_ICONINFORMATION);
    }
    else
    {
        MessageBox(TEXT("   請(qǐng)先輸入要發(fā)送給匿名管道的數(shù)據(jù) ..."), 
            TEXT("提示"), MB_ICONERROR);
    }
}
 
//需要獲取繼承自父進(jìn)程的匿名管道讀寫(xiě)句柄
void CNoNamedPipeChildDlg::GetReadWriteHandleFromParent(void)
{
    if(this->m_IsGettedParentHandle == FALSE)
    {
        hPipeRead = GetStdHandle(STD_INPUT_HANDLE);
        hPipeWrite = GetStdHandle(STD_OUTPUT_HANDLE);
 
        this->m_IsGettedParentHandle = TRUE;
    }
}

效果展示:

首先需要將子進(jìn)程的可執(zhí)行文件拷貝到父進(jìn)程所在目錄下,否則創(chuàng)建進(jìn)程時(shí)會(huì)找不到子進(jìn)程的可執(zhí)行文件。 

image

啟動(dòng)父進(jìn)程可執(zhí)行文件,并單擊創(chuàng)建匿名管道按鈕,此時(shí)會(huì)彈出子進(jìn)程窗口(新建了進(jìn)程):

image

再在父進(jìn)程的左邊文本框中輸入數(shù)據(jù),單擊寫(xiě)入數(shù)據(jù)按鈕:

image

再在子進(jìn)程窗口中單擊讀取數(shù)據(jù)按鈕:

image

再在子進(jìn)程窗口左邊的文本框中輸入數(shù)據(jù),單擊寫(xiě)入數(shù)據(jù)按鈕:

image

再在父進(jìn)程窗口中單擊讀取數(shù)據(jù)按鈕:

image

             

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多