同过匿名通道来实现父子进程见通信

匿名通道,我这里是同步方式,至于异步,好像与OVERLAPPED有关,这里就不多叙述了,我自己也还不是很明白

说下流程

首先在父进程里面创建一个管道,CreatePipe,这个函数第一,二个参数都是传出句柄,用于对管道的读出和写入句柄,第三个参数是安全性描述符,这里就省去了,使用默认的,第四个参数是你要为这个缓冲区分配多少字节的内存,

由于匿名管道只可以实现进程内部,或者父子进程之间的通信。另外你往管道里面些数据,如果两次写入,而为读出,那么管道里将是第一次写入数据,第二次写入作废,读是“破坏性”地去读,也就是你这次读出了数据,瑕疵这数据就不见了,当缓冲去里面没有数据的时候,去读的话,如果没有采用OVERLAPPED技术的话,那么处理机将会处于忙等状态,直到有数据写入时候才会返回,否则会一直处于假死的状态,这中同步方式通信,必然是低效的


对于父,子进程中的读管道操作都是一样的,因为两者都是调用ReadFile与WriteFile,ReadFile,第一个参数是读句柄,后面的参数是要写数据的大小,缓冲区大小,实际读大小,是否用OVERLAPPED技术,如果不用,最后一个参数设置为0

WriteFile第一个参数也是写句柄,发送大小,发送缓冲区,实际发送大小,是否采用OVERLAPPED技术,不用就设置为NULL


那么父进程的句柄如何传递给子进程呢,通过创建进程时候,指定子进程的标准输入输出以及错误句柄,然后子进程通过 hRead = GetStdHandle(STD_INPUT_HANDLE);

std_output_handle,std_error_handle来把进程句柄进行传递,创建子进程时候,是否继承父进程打开的句柄,设置为true,否则子进程无法拿到句柄

这里在说明自己犯的一个错误,我在获得写句柄的时候GetStdHandle穿进去参数用STD_INPUT_HANDLE来给写入句柄,这是错误的,然后写文件的时候就出错了,然后用GetLastError来获得进程的错误信息,发现返回5,意思是访问拒绝,粗心啊,找了半天这个错误


好了贴个图

然后贴上自己代码

父进程中代码

// 剪贴板通信Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "剪贴板通信.h"
#include "剪贴板通信Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// C剪贴板通信Dlg 对话框




C剪贴板通信Dlg::C剪贴板通信Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(C剪贴板通信Dlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void C剪贴板通信Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(C剪贴板通信Dlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_SENDMESSAGE, &C剪贴板通信Dlg::OnBnClickedSendmessage)
	ON_BN_CLICKED(IDC_RECVMESSAGE, &C剪贴板通信Dlg::OnBnClickedRecvmessage)
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_CREATE, &C剪贴板通信Dlg::OnBnClickedCreate)
END_MESSAGE_MAP()


// C剪贴板通信Dlg 消息处理程序

BOOL C剪贴板通信Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void C剪贴板通信Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void C剪贴板通信Dlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR C剪贴板通信Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void C剪贴板通信Dlg::OnBnClickedSendmessage()
{
//#define _unicode

	// TODO: 在此添加控件通知处理程序代码
	/*//加入提供汉字的支持,SetClipboardData指定文本格式为CF_UNICODETEXT,复制的时候用wcscp
	if(this->OpenClipboard())
	{
		CString str;
		wchar_t * pBuf;
		EmptyClipboard();
		GetDlgItemText(IDC_SEND,str);
		//HGLOBAL hClip = GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);
		HGLOBAL hClip  = (wchar_t *)GlobalAlloc(GHND,sizeof(wchar_t) + str.GetLength()*2);
		pBuf = (wchar_t*)GlobalLock(hClip);
		wcscpy(pBuf,str);
		GlobalUnlock(hClip);
		SetClipboardData(CF_UNICODETEXT,hClip);
		CloseClipboard();
	}
	else
	{
		MessageBox(TEXT("@打开剪贴板失败@"));
	}*/
	
	//匿名通道写
	char recvbuf[100] = "we all like operation system";
	DWORD num;
	if(!WriteFile(hWrite,recvbuf,strlen(recvbuf)+1,&num,NULL))
	{
		MessageBox(TEXT("Error In Write File"));
		return;
	}
	//MessageBox(CString(recvbuf));

}

void C剪贴板通信Dlg::OnBnClickedRecvmessage()
{
	// TODO: 在此添加控件通知处理程序代码

	/*if(OpenClipboard())
	{
		if(IsClipboardFormatAvailable(CF_UNICODETEXT))
		{
			HANDLE hClip = GetClipboardData(CF_UNICODETEXT);
			wchar_t * pBuf =(wchar_t*) GlobalLock(hClip);
			SetDlgItemText(IDC_RECV,pBuf);

		}
		CloseClipboard();
	}*/

	//匿名管道通信
	char buf[100];
     DWORD num;
	if(!ReadFile(hRead,buf,100,&num,NULL))
	{
		MessageBox(TEXT("读取数据失败"));
		return;
	}
	MessageBox(CString(buf));
}

void C剪贴板通信Dlg::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(hRead)
		CloseHandle(hRead);
	if(hWrite)
		CloseHandle(hWrite);

	CDialog::OnClose();
}

void C剪贴板通信Dlg::OnBnClickedCreate()
{
	// TODO: 在此添加控件通知处理程序代码

	/*SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL ;
	sa.bInheritHandle = true;

	if(!CreatePipe(&hRead,&hWrite,&sa,0))
	{
		MessageBox(TEXT("&Error In Create Pipe&"));
		return ;
	}
	
   STARTUPINFO sui; 
   PROCESS_INFORMATION  pi;
   ZeroMemory(&sui,sizeof(STARTUPINFO));
   sui.cb = sizeof(STARTUPINFO);
   sui.hStdInput = hRead;
   sui.hStdOutput = hWrite;
   sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);
   sui.dwFlags = STARTF_USESTDHANDLES;
  

	if(!CreateProcess(TEXT("..\\Debug\\Child.exe"),NULL,NULL,NULL,true,0,NULL,NULL,&sui,&pi))
	{
		DWORD ni= GetLastError();

		MessageBox(TEXT("Error In Create Process"));
		CloseHandle(hRead);
		CloseHandle(hWrite);
		hRead = NULL;
		hWrite = NULL;
		return ;
	}
	else
	{
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
	}*/
	SECURITY_ATTRIBUTES  sa;
	sa.bInheritHandle = true;
	sa.lpSecurityDescriptor = NULL;
	sa.nLength =sizeof(SECURITY_ATTRIBUTES);
	if(!CreatePipe(&hRead,&hWrite,&sa,0))
	{
		MessageBox(_T("创建管道失败!"));
		return;
	}
 //NULL

	STARTUPINFO sui;
	PROCESS_INFORMATION  pi;
	ZeroMemory(&sui,sizeof(STARTUPINFO));
	sui.cb = sizeof(STARTUPINFO);
	sui.dwFlags =STARTF_USESTDHANDLES;
	sui.hStdInput =hRead;
	sui.hStdOutput =hWrite;
	sui.hStdError =GetStdHandle(STD_ERROR_HANDLE);
	if(!CreateProcess(_T("..\\Debug\\child.exe"),NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi))
	{
		int s = GetLastError();
		CloseHandle(hRead);
		CloseHandle(hWrite);
		hRead = NULL;
		hWrite =NULL;
		MessageBox(_T("创建进程失败!"));
		return;
	}
	else
	{
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
	}
	
}

子进程中的代码

// ChildDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Child.h"
#include "ChildDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CChildDlg 对话框




CChildDlg::CChildDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CChildDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	hRead = NULL;
	hWrite = NULL;
}

void CChildDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CChildDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_READ, &CChildDlg::OnBnClickedRead)
	ON_BN_CLICKED(IDC_WRITE, &CChildDlg::OnBnClickedWrite)
	ON_WM_CLOSE()
	ON_WM_CREATE()
END_MESSAGE_MAP()


// CChildDlg 消息处理程序

BOOL CChildDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CChildDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CChildDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CChildDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CChildDlg::OnBnClickedRead()
{
	// TODO: 在此添加控件通知处理程序代码

	char buf[100];
     DWORD num;
	if(!ReadFile(hRead,buf,100,&num,NULL))
	{
		MessageBox(TEXT("读取数据失败"));
		return;
	}
	MessageBox(CString(buf));
}

void CChildDlg::OnBnClickedWrite()
{
	// TODO: 在此添加控件通知处理程序代码
	

	/*char buf[]= "we all like operation";
	DWORD num;
	if(!WriteFile(hWrite,buf,strlen(buf)+1,&num,NULL))
	{
		DWORD dw = GetLastError();
		CString str;
		str.Format(TEXT("%u"),dw);
		MessageBox(str);
		//MessageBox(TEXT("Error In Write File"));
		return;
	}
	//MessageBox(CString(buf));*/
	char pBuf[]="hello world!";
	DWORD dwWrite;
	if(!WriteFile(hWrite,pBuf,strlen(pBuf)+1,&dwWrite,NULL))
	{
		MessageBox(TEXT("读取数据失败!"));
		return;
	}
}

void CChildDlg::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
  	if(hRead)
		CloseHandle(hRead);
	if(hWrite)
		CloseHandle(hWrite);

	CDialog::OnClose();
}

int CChildDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDialog::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	 hRead = GetStdHandle(STD_INPUT_HANDLE);
	 hWrite = GetStdHandle(STD_OUTPUT_HANDLE);

	return 0;
}

OK ,that' all ,今天考六级,蛋疼啊,后面还有三门课程和一个项目,注定蛋筒 啊,苦逼的娃子啊 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值