`
runfeel
  • 浏览: 904495 次
文章分类
社区版块
存档分类
最新评论

匿名管道

 
阅读更多
管道(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;
  }
分享到:
评论

相关推荐

    易语言匿名管道类

    易语言匿名管道 .版本 2 .支持库 spec ' 通过类创建回显线程 调试输出 (匿名管道.运行 (“cmd”, “D:\”, &显示线程, )) ' 单独运行读管道里自己启动线程 ' 匿名管道.运行_匿名管道 (, , , ) ' 启动线程 (&显示...

    匿名管道与命名管道的使用

    管道分类: 根据进程的相互关系,可以分为:匿名管道与命名管道。 1 匿名管道:管道是父进程和子进程间,或是子进程与子进程间单向的通讯机制,即一个进程发送数据到管道,另外一个进程从管道中读出数据。如果需要...

    易语言匿名管道类模块

    易语言匿名管道类模块源码,匿名管道类模块,运行,读,写,显示线程,创建匿名管道,获取启动信息,创建进程,读文件,写文件

    匿名管道实例 C++

    匿名管道实例C++程序,先打开child.exe,执行parent程序就可。

    匿名管道代码实例

    匿名管道是一种未命名的、单向管道,通常用来在一个父进程和一个子进程之间传输数据。匿名的管道只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。为了研究windows进程间通信方法,顺手写了几篇demo供...

    匿名管道的使用

    匿名管道的使用,基本上的API用上了,了解匿名管道请上http://www.dayif.cn/?p=182

    使用匿名管道实现进程通信

    使用匿名管道实现进程通信 使用匿名管道实现进程通信 使用匿名管道实现进程通信

    匿名管道及双管道后门,后门技术

    匿名管道及双管道后门,后门技术匿名管道及双管道后门,后门技术

    delphi匿名管道技术

    delphi匿名管道技术 100%能用的。没应用程序 不是控制台。。体积300多K

    C++与ADB通讯匿名管道-双向通讯-.7z

    匿名管道双向通讯,可用于替代windows cmd 接管adb输入输出。匿名管道双向通讯,可用于替代windows cmd 接管adb输入输出。

    匿名管道实现进程间通信示例程序

    匿名管道实现进程间通信示例程序匿名管道实现进程间通信示例程序

    匿名管道示例代码 vc

    匿名管道示例代码 vc6 用途:比如象IDE一样,运行一个CONSOLE程序,显示在自己的GUI界面里.

    MFC匿名管道通信双向通信 VS2012源码

    MFC匿名管道通信双向通信 VS2012源码 MFC匿名管道通信双向通信 VS2012源码 MFC匿名管道通信双向通信 VS2012源码

    匿名管道通信例子

    使用MFC实现的匿名管道通信的例子

    匿名管道重定向cmd

    适合学习但又搞不懂的新手,了解匿名管道的重定向作用

    MFC匿名管道通信

    基于MFC的匿名管道通信,父子进程实时通信实时显示。操作系统API

    基于匿名管道的cmd回显

    本机基于匿名管道的cmd回显,vc,功能较简单可扩充

    进程间通信之匿名管道demo

    利用匿名管道来实现进程间通信,双向。注意这种方式只能在父子进程中使用。使用方法: 两个exe,一个客户端,一个服务器,两个exe必须在同一目录下,打开NoNamedPipeParent.exe,点击创建匿名管道,此时会创建一个...

    易语言源码易语言匿名管道类模块源码.rar

    易语言源码易语言匿名管道类模块源码.rar

Global site tag (gtag.js) - Google Analytics