进程间通信-匿名管道

匿名管道一般用于父子间进程通信

注意:匿名管道不允许异步操作,所以如在一个管道中写入数据,且缓冲区已满,那么除非另一个进程从管道中读出数据,从而腾出了缓冲区的空间,否则写入函数不会返回,还有如果管道中没有数据的话,读端那边会一直等待数据读取,会操作堵塞所以要用PeekNamedPipe这个api去获取管道中的数据,如果有数据的话就读取

因为匿名管道是单向的,只能一端读一端写,所以父子进程中能有读写两种操作必须得要创建两条管道

代码例子如下

父进程创建两条管道,把两条管道中一个读一个写分别给子进程

SECURITY_ATTRIBUTES sa;
  sa.nLength = sizeof(sa);
  sa.bInheritHandle = TRUE;//设置管道的句柄可以继承,这样子进程才能继承到父进程的句柄从而获取到句柄
  sa.lpSecurityDescriptor = NULL;

  BOOL bRet = CreatePipe(
    &m_hReadParent,  //读出端句柄
    &m_hWriteChild, //写入端句柄
    &sa,
    0); //使用默认的缓冲区大小

  bRet = CreatePipe(
    &m_hReadChild,  //读出端句柄
    &m_hWritePrent, //写入端句柄
    &sa,
    0); //使用默认的缓冲区大小

  STARTUPINFO si;
  PROCESS_INFORMATION pi;

  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  si.dwFlags = STARTF_USESTDHANDLES;
  si.hStdInput = m_hReadChild;//用于设定进程的标准输入输出的句柄

  si.hStdOutput = m_hWriteChild;//
  ZeroMemory(&pi, sizeof(pi));

  TCHAR szName[] = { _T("SubProcess") };

  // Start the child process. 
  if (!CreateProcess(NULL, 
    szName, 
    NULL,             
    NULL,            
    TRUE, //继承父进程的句柄          
    0,              
    NULL,           
    NULL,            
    &si, //这时候需要把管道的句柄传进子进程了          
    &pi)           
    )
  {
    AfxMessageBox(_T("CreateProcess failed."));
  }

父进程读写

CString csBuff;
  GetDlgItemText(EDT_WRITE2, csBuff);
  DWORD dwBytesToWrite = 0;
  BOOL bRet = WriteFile(
    m_hWritePrent,
    csBuff.GetBuffer(),
    csBuff.GetLength()*sizeof(TCHAR),
    &dwBytesToWrite,
    NULL);
  if (!bRet)
  {
    AfxMessageBox(_T("写入管道失败!"));
  }
TCHAR szBuff[MAXBYTE] = { 0 };
  DWORD dwBytesToRead = 0;
  DWORD dwBytesAvail = 0;  //管道中可用字节数
  PeekNamedPipe(m_hReadParent, NULL, NULL, NULL, &dwBytesAvail, NULL);

  //如果管道中还有数据,则读取
  if (dwBytesAvail > 0)
  {
    BOOL bRet = ReadFile(
      m_hReadParent,
      szBuff,
      sizeof(szBuff),
      &dwBytesToRead,
      NULL);
    if (!bRet)
    {
      AfxMessageBox(_T("读入管道失败!"));
    }

    SetDlgItemText(EDT_READ2, szBuff);
  }

子进程获取句柄进行读写操作

 //获取读出端句柄
  STARTUPINFO si;
  GetStartupInfo(&si);

  TCHAR szBuff[MAXBYTE] = { 0 };
  DWORD dwBytesToRead = 0;
  DWORD dwBytesAvail = 0;  //管道中可用字节数
  PeekNamedPipe(si.hStdInput, NULL, NULL, NULL, &dwBytesAvail, NULL);

  //如果管道中还有数据,则读取
  if (dwBytesAvail > 0)
  {
    BOOL bRet = ReadFile(
      si.hStdInput,
      szBuff,
      sizeof(szBuff),
      &dwBytesToRead,
      NULL);
    if (!bRet)
    {
      AfxMessageBox(_T("写入管道失败!"));
    }

    SetDlgItemText(EDT_READ, szBuff);
  }

//获取写出端句柄
 /* STARTUPINFO si;
  GetStartupInfo(&si);
  si.hStdOutput;*/
  HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//第二种方法也可以获取管道读写句柄,因为我在父进程哪里把子进程的标准输入输出句柄设置为管道的读写句柄

  CString csBuff;
  GetDlgItemText(EDT_WRITE, csBuff);
  DWORD dwBytesToWrite = 0;
  BOOL bRet = WriteFile(
    hOutput,
    csBuff.GetBuffer(),
    csBuff.GetLength()*sizeof(TCHAR),
    &dwBytesToWrite,
    NULL);
  if (!bRet)
  {
    AfxMessageBox(_T("写入管道失败!"));
  }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值