管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。
  
    匿名管道实施细则
  
    匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:
  
  BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针
   PHANDLE hWritePipe, // 指向写句柄的指针
   LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针
   DWORD nSize // 管道大小
  ); 
  
    通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。在使用匿名管道通信时,服务器进程必须将其中的一个句柄传送给客户机进程。句柄的传递多通过继承来完成,服务器进程也允许这些句柄为子进程所继承。除此之外,进程也可以通过诸如DDE或共享内存等形式的进程间通信将句柄发送给与其不相关联的进程。 
  
    在调用CreatePipe()函数时,如果管道服务器将lpPipeAttributes 指向的SECURITY_ATTRIBUTES数据结构的数据成员bInheritHandle设置为TRUE,那么CreatePipe()创建的管道读、写句柄将会被继承。管道服务器可调用DuplicateHandle()函数改变管道句柄的继承。管道服务器可以为一个可继承的管道句柄创建一个不可继承的副本或是为一个不可继承的管道句柄创建一个可继承的副本。CreateProcess()函数还可以使管道服务器有能力决定子进程对其可继承句柄是全部继承还是不继承。
  
    在生成子进程之前,父进程首先调用Win32 API SetStdHandle()使子进程、父进程可共用标准输入、标准输出和标准错误句柄。当父进程向子进程发送数据时,用SetStdHandle()将管道的读句柄赋予标准输入句柄;在从子进程接收数据时,则用SetStdHandle()将管道的写句柄赋予标准输出(或标准错误)句柄。然后,父进程可以调用进程创建函数CreateProcess()生成子进程。如果父进程要发送数据到子进程,父进程可调用WriteFile()将数据写入到管道(传递管道写句柄给函数),子进程则调用GetStdHandle()取得管道的读句柄,将该句柄传入ReadFile()后从管道读取数据。
  
    如果是父进程从子进程读取数据,那么由子进程调用GetStdHandle()取得管道的写入句柄,并调用WriteFile()将数据写入到管道。然后,父进程调用ReadFile()从管道读取出数据(传递管道读句柄给函数)。
  
    在用WriteFile()函数向管道写入数据时,只有在向管道写完指定字节的数据后或是在有错误发生时函数才会返回。如管道缓冲已满而数据还没有写完,WriteFile()将要等到另一进程对管道中数据读取以释放出更多可用空间后才能够返回。管道服务器在调用CreatePipe()创建管道时以参数nSize对管道的缓冲大小作了设定。
  
    匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调用CloseHandle()函数来关闭此句柄
  
  
  
  /
  匿名管道程序示例
  
    总的来说,匿名管道程序是比较简单的。在下面将要给出的程序示例中,将由父进程(管道服务器)创建一个子进程(管道客户机),子进程回见个其全部的标准输出发送到匿名管道中,父进程再从管道读取数据,一直到子进程关闭管道的写句柄。其中,匿名管道服务器程序的实现清单如下:
  
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  char ReadBuf[100];
  DWORD ReadNum;
  HANDLE hRead; // 管道读句柄
  HANDLE hWrite; // 管道写句柄
  BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 创建匿名管道
  if (bRet == TRUE)
   printf("成功创建匿名管道!\n");
  else
   printf("创建匿名管道失败,错误代码:%d\n", GetLastError());
   // 得到本进程的当前标准输出
   HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
   // 设置标准输出到匿名管道
   SetStdHandle(STD_OUTPUT_HANDLE, hWrite);
   GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息
   bRet = CreateProcess(NULL, "Client.exe", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 创建子进程
   SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢复本进程的标准输出
   if (bRet == TRUE) // 输入信息
    printf("成功创建子进程!\n");
   else
    printf("创建子进程失败,错误代码:%d\n", GetLastError());
    CloseHandle(hWrite); // 关闭写句柄
    // 读管道直至管道关闭
    while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))
    {
     ReadBuf[ReadNum] = '\0';
     printf("从管道[%s]读取%d字节数据\n", ReadBuf, ReadNum);
    }
    if (GetLastError() == ERROR_BROKEN_PIPE) // 输出信息
     printf("管道被子进程关闭\n");
    else
     printf("读数据错误,错误代码:%d\n", GetLastError()); 
  
    在本示例中,将当前进程的标准输出设置为使用匿名管道,再创建子进程,子进程将继承父进程的标准输出,然后再将父进程的标准输出恢复为其初始状态。于是父进程便可从管道读取数据,直到有错误发生或关闭管道写入端的所有句柄。创建的子进程只是向标准输出和标准错误发送一些文本信息,其中发送给标准输出的文本将重定向输出到管道,发送给标准错误的文本将不改变输出。下面给出子进程的实现代码:
  
  int main(int argc, char* argv[])
  {
   for (int i = 0; i < 100; i++) // 发送一些数据到标准输出和标准错误
   {
    printf("i = %d\n", i); // 打印提示
    cout << "标准输出:" << i << endl; // 打印到标准输出
    cerr << "标准错误:" << i << endl; // 打印到标准错误
   }
   return 0;

  }

CreatePipe匿名管道通信相关推荐

  1. 2.12父子进程通过匿名管道通信

    目录 1.pipe函数 2.查看管道缓冲大小 1.pipe函数 #include <unistd.h> int pipe(int pipefd[2]);功能:创建一个匿名管道,用来进程间通 ...

  2. Visual C++下对匿名管道的编程实现

    可以使用管道 Visual C++下对匿名管道的编程实现 概述 管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机.一个进程在向管道写入 ...

  3. Linux编程:多个子进程与父进程使用匿名管道读写

    编写程序,在程序中父进程先后创建子进程1和子进程2.父子三个进程并发执行,并利用同一个匿名管道通信:两个子进程分别向管道写一则信息(内容自定,但要求包含子进程信息):父进程从管道读出信息并显示出来(要 ...

  4. 【Linux】进程间通信--管道(匿名管道和命名管道)

    文章目录 前言 进程间通信的目的 管道 匿名管道 管道特点 站在文件描述符角度理解管道 匿名管道通信读写特点 命名管道 命名管道的原理 命名管道的创建 命名管道完成两个不同进程通信 匿名管道和命名管道 ...

  5. 【Linux】进程间通信 —— 匿名管道 | 命名管道 | System V | 消息队列 | 共享内存

    进程间通信 0. 进程间通信 1. 管道 1.1 匿名管道 1.1.1 匿名管道原理 1.1.2 创建匿名管道pipe 1.1.3 基于匿名管道通信的4种情况5个特点 1.2 命名管道 1.2.1 创 ...

  6. 8、进程通信-匿名管道

    匿名管道 一个单向,未命名的管道,通常用来在一个父进程和一个子进程间传输数据.只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信. BOOL CreatePipe( PHANDLE hRead ...

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

    上一篇<进程通信之二 管道技术第一篇 输入输出的重定向>示范了增加若干程序代码来完成程序输入输出的重定向,并提出了如果没有程序源代码,只有程序文件如何来完成重定向.本篇就介绍如何使用匿名管 ...

  8. 进程通信:匿名管道和命名管道

    一.进程间通信方式 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. 有名管道 (named pipe) : ...

  9. Linux进程通信——匿名管道、命名管道、管道的特性和共享内存

    Linux进程通信--匿名管道.命名管道.管道的特性和共享内存 一.管道 1.1 什么是管道? 1.2 匿名管道 <1> 匿名管道参数说明 <2> fork共享管道原理 < ...

最新文章

  1. Android视图动画集合AndoridViewAnimations
  2. mess组网 中继_取代中继/子母路由 堪称最上乘的Mesh组网方式了解下
  3. NOIp 2014 #2 联合权值 Label:图论 !!!未AC
  4. why is list delete and edit icon rendered
  5. Teradata天睿公司推出适用各种部署环境的全球最强分析数据库
  6. ROS学习笔记四:用C++编写ROS发布与订阅
  7. 关于静态库、动态库的区别汇总
  8. 袁大头 如何辨别假货
  9. 双电容单相电机接线图解_单相电机要用电容,三相电机为何不需要?
  10. PDE7 wave equation: intuition
  11. WebService 教程
  12. 单片机1到十五c语言,手把手教你学单片机的C语言程序设计(十五).pdf
  13. bim 水利枢纽 运维_BIM技术与现代化建筑运维管理
  14. 萤石云平台接入_新手上路 老司机教你配置萤石云
  15. Git操作流程(非常详细)
  16. Hashcode底层实现原理
  17. 如何构建VoIP来是实现电话诈骗之——Asterisk的设置
  18. 真是「狗」了,知乎「吃相」太难看了
  19. 复旦大学计算机学院教师简介,复旦大学计算机科学技术学院导师教师师资介绍简介-危辉...
  20. SAP access 破解

热门文章

  1. 数据库-优化-通过慢查日志查询有问题的sql
  2. 实现runable接口创建线程
  3. Date类的构造方法和成员方法
  4. oracle11 不更新记录,oracle11g 使用first_value获取表中不连接的ID号及掉失记录数量...
  5. ios键盘横屏_iOS横竖屏旋转及其基本适配方法 转
  6. 解决 Maven 报错 Non-resolvable parent POM ... was cached in the local repository, resolution will not be
  7. Redis持久化方式的选择
  8. 前端js实现字符串/图片/excel文件下载
  9. 国家文物局:长城沿线群众是文物保护的重要力量
  10. 探析“Java序列化”之serialVersionUID