windows下匿名管道的使用

  windows中有时候需要使用多进程进行编程,有的时候是因为一个复杂的过程需要开启一个新的进程进行处理,又或者仅仅是需要调用一个已经存在的exe等等,创建多个进程时,进程之间的通信是一个重要的问题,下面讨论一下如何使用匿名管道,在父子进程中进行通信。

  使用情况:父进程使用createProcess与子进程进行通信。

  管道(pipe)和现实中的管道的作用非常相似,从一端放入东西(数据),这些东西(数据)就可以通过管道,从另一端被取出来。在这里,管道的两端就是计算机上需要通信的两个进程,一个进程向管道发送数据,另一个进程从管道读取数据,这样就完成了进程间的通信。

  首要问题:两个进程既然要通过管道进行通信,那么这两个进程必须获得一个(同一个)管道,当父进程创建了一个管道之后,子进程如何得到父进程创建的这个管道呢,如果这个管道是此处所讨论的匿名管道,那么子进程可以会通过集成的方式的到父进程创建的管道。

  由于父进程创建子进程的时候,子进程并没有集成父进程的地址空间(每个进程都有自己独立的地址空间),所以子进程并不能直接访问父进程的数据,也就是说这两个进程之间无法向同一个进程中不同的线程那样直接使用变量等进行通信。但是子进程创建之后会集成父进程所创建的能够被继承的句柄,因此,在父进程创建管道的时候(实际上或得到创建的管道的句柄),通过制定这个管道句柄为可集成的,创建子进程的时候,这个句柄就有机会被子进程集成得到(实际上还需要在调用createProcess函数创建子进程时指明继承特性,如下述)。

  创建管道函数如下:

  BOOL __stdcal CreatePipe(
       PHANDLE hReadPipe,
       PHANDLE hWritePipe,
      LPSECURITY_ATTRIBUTES lpPipeAttributes,
      DWORD nSize
      );

  其中hReadPipe,hWritePipe这两个句柄为创建的管道的写句柄和读句柄,从名称就可以看出,我们使用hWritePipe句柄向管道写入数据,使用hReadPipe句柄从管道读出数据,nSize指定创建管道的大小,如果为0,则使用windows提供的默认值。

  第三个参数是一个LPSECURITY_ATTRIBUTES类型的结构体,定义如下:

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

  nLength永远被设置为sizeof(SECURITY_ATTRIBUTES),lpSecurityDescriptor为安全描述符,可以简单设置为NULL,使用默认设置,与本处讨论无关,第三个参数bInheritHandle设置为true时,表示使用这个安全属性(SECURITY_ATTRIBUTES)创建的内核对象,是可以被子进程继承的,同理,如果bInheritHandle为false,子进程则无法继承父进程创建的相应句柄,也就无法对这个句柄进行访问。

  到此,第一个问题就解决了。在父进程中创建一个管道句柄,创建的时候通过设置参数lpPipeAttributes的成员bInheritHandle为true,使得子进程可以继承到父进程创建的句柄,那么子进程该如何使用父进程创建的句柄呢,显然它无法直接取得父进程的任何变量,那么就有了第二个问题,句柄的传递。

  在讨论父进程如何将句柄传递给子进程之前,有必要先看一下创建子进程的函数:

BOOL __stdcal CreateProcess(
      LPCSTR lpApplicationName,
      LPSTR lpCommandLine,
      LPSECURITY_ATTRIBUTES lpProcessAttributes,
      LPSECURITY_ATTRIBUTES lpThreadAttributes,
      BOOL bInheritHandles,
        DWORD dwCreationFlags,
      LPVOID lpEnvironment,
      LPCSTR lpCurrentDirectory,
      LPSTARTUPINFOA lpStartupInfo,
      LPPROCESS_INFORMATION lpProcessInformation
    );

  其中lpApplicationName设定子进程的名字,lpCommandLine设定子进程的参数,lpProcessAttributes和lpThreadAttributes设定子进程的安全性,dwCreationFlags设定子进程将如何创建,lpEnvironment设定子进程的环境块,lpCurrentDirectory设定子进程的当前目录,这些与本主题关系不大,不详加解释。具体用法可查阅相关资料。进程创建过程中,本函数提供了进程创建需要的各种参数,其中的bInheritHandles,在本主题至关重要,如果希望子进程能够继承父进程的句柄,需要设置bInheritHandles为true,这样,在子进程中就能访问父进程中那些可以被继承的句柄,对父进程中那些不能继承的句柄,子进程依旧不能访问。若bInheritHandles为false,则子进程不能访问父进程所有的句柄。父进程创建的句柄可以通过lpCommandLine参数传递给子进程,下面以创建文件句柄为例给出具体方法:

父进程中:HANDLE file;

... ...

createProcess("child.exe",(char*)&file,0,0,TRUE,NULL,0,0,&StartupInfo,&ProcessInformation);

创建成功后,子进程中:

HANDLE cFile = (HANDLE)(*argv[0]);

  这样,在子进程中就可以得到父进程传递过来的文件句柄,从而对文件进行读写。此处是父子进程之间进行通信,我们采用另一种方法传递句柄。

  createProcess中的参数lpStartupInfo里面有很多的成员,在此不一一列举,我们只看我们所需要的三个:hStdError,hStdOutput,hStdInput,也就是标准错误输出句柄,标准输出句柄,标准输入句柄。在父进程中可以指定子进程的这三个句柄,父进程可以通过将createPipe生成的句柄付给这三个句柄,之后在子进程中,子进程将标准句柄取出,即得到了父进程传递给它的句柄,从而可以使用这个句柄进行沟通:

  可能的简要伪代码如下:

  父进程:

  CreatePipe(&hRead, &hWrite, &saAttr, 0);

  STARTUPINFO ssi;

     ssi.hStdError = hWrite;
     ssi.hStdOutput = hWrite;

   createProcess("child.exe",handleBuffer,0,0,TRUE,NULL,0,0,&ssi,&ProcessInformation);

  readMessage(hRead);

  子进程:

  HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

  writeMessage(hStdout);

 

 

 

 

 

转载于:https://www.cnblogs.com/gtl001/p/3656884.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 无名管道(Anonymous Pipe)是操作系统中用于实现进程间通信(IPC)的一种机制,Windows操作系统也支持使用无名管道进行进程间通信。 在Windows操作系统中,无名管道是一种特殊类型的文件,只能用于相关进程间通信,无法用于不相关进程间通信。无名管道通常是单向的,有一个读取端(Read end)和一个写入端(Write end),一个进程可以往管道的写入端写入数据,另一个进程可以从管道的读取端读取数据。 无名管道常用于兄弟进程间通信(如父子进程)或者由同一个进程创建的两个进程间通信。 使用无名管道进行进程间通信的步骤如下: 1. 创建管道:调用CreatePipe函数创建一个无名管道,返回读取端和写入端句柄。 2. 创建进程:使用CreateProcess函数创建需要进行通信的进程。 3. 设置进程的标准输入输出:使用SetStdHandle函数将管道的读取端和写入端句柄分别设置为所创建进程的标准输入和标准输出。 4. 进程通信:通过写入端句柄向管道写入数据,然后通过读取端句柄从管道读取数据。 在这个过程中,写入端和读取端可以位于同一个进程中,也可以位于不同的进程中。写入端写入的数据会被读取端读取,实现了进程间的通信。 无名管道可以用于传输任意类型的数据,包括文本、二进制等。只要进程通过读取端和写入端的兼容接口进行数据的读写操作,就可以实现进程间的通信。 总之,使用无名管道是一种简单有效的方式来实现Windows操作系统中进程间的通信,通过读取端和写入端的数据传输,可以实现数据的共享和交换,满足进程间通信的需求。 ### 回答2: 无名管道(Anonymous Pipes)是一种在Windows系统中用于实现进程间通信的机制。它通常用于在父子进程之间或者兄弟进程之间进行数据传输。 在使用无名管道之前,我们需要创建一个匿名管道对象,它定义了一个读取端和一个写入端。父进程可以通过创建管道对象,并将写入端传递给子进程,来实现进程间通信。子进程可以通过读取从父进程写入端传来的数据来获取信息。 无名管道使用步骤如下: 1. 使用CreatePipe函数创建一个无名管道,该函数返回两个句柄(一个读句柄和一个写句柄),分别用于读取和写入管道中的数据。 2. 通常,我们会在父进程中调用CreateProcess函数创建一个子进程。子进程会继承父进程的句柄。 3. 在创建子进程后,父进程可以关闭子进程中不需要的句柄(写句柄),子进程可以关闭父进程中不需要的句柄(读句柄)。 4. 当父进程想要向子进程发送数据时,它可以使用WriteFile函数来向写入端写入数据。 5. 子进程可以使用ReadFile函数从读取端读取父进程写入的数据。 通过这种方式,父进程和子进程之间可以进行双向的通信。 需要注意的是,无名管道只适用于具有亲密关系(比如父子进程)或具有共同祖先(比如兄弟进程)的进程之间。此外,无名管道是半双工的,意味着只能在一个方向上传递数据。如果需要实现双向通信,可以使用两个无名管道来分别实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值