命名管道(Named Pipe)服务

命名管道(Named Pipe)服务

1  命名管道的名称解析

在Windows中,管道的名称遵循Windows统一命名规范(UNC,Universal Naming Convention)。

命名管道的名称格式为\\<Server>\Pipe\<PipeName>。<Server>指定了一个命名管道的服务器所在的计算机名称,既可以是DNS名称,也可以是NetBIOS名称或者字符串形式的IP地址;<PipeName>是管道的唯一名,可以是层次结构中的一个全路径名,即允许包含多级目录。例如:\\MyServer\Pipe\MyAppServer\ConnectionPipe。

使用CreateNamedPipe API创建命名管道时,必须指定一个形如\\.\Pipe\<PipeName>的本地名称,“.”代表本地系统。NtCreateNamedFile 接收到的名称为“\??\PIPE\<PipeName>”,对象管理器会将此名称变为”\Global??\PIPE\<PipeName>”,”\Global??\PIPE”是一个符号链接,指向设备对象”\Device\NamedPipe”,对象管理器找到该设备对象,由它所属的驱动程序进一步解析剩下的子串,这就进入到了命名管道驱动程序中。

命名管道实际上是本地的一个文件系统,npfs就代表了命名管道文件系统(named pipe file system) 。每个命名管道等同于一个文件对象,与普通文件系统中的文件不同的是,命名管道是动态对象,它没有永久状态。一个命名管道的存在总是伴随着一个服务器和一个客户,其职责是为服务器和客户提供一个双向交换数据的通道。

2  命名管道的通讯模型

如图:

  1. 服务器进程调用CreateNamePipe 创建一个有名称的命名管道,同时指定最大允许的实例数(1~255)。
  2. 服务器进程调用ConnectNamedPipe,以等待客户的连接请求,可以是同步形式(阻塞)或异步方式(要求在创建命名管道时指定了FILE_FLAG_OVERLAPPED标志),若是同步方式,那么ConnectNamedPipe返回时,客户与服务器之间的名叫管道连接已经建立起来。
  3. 客户进程调用CreateFile 连接到一个正在等待连接的命名管道上。CreateFile 成功返回后,至此服务器进程的ConnectNamedPipe 完成其建立连接的任务。
  4. 双方调用ReadFile/WriteFile 或ReadFileEx/WriteFileEx ,从管道中读取或写入数据。

 

服务器进程可以调用DisconnectNamedPipe ,将一个管道实例与当前建立连接的客户进程断开,可以重新连接到新的客户进程。CloseHandle 关闭命名管道。

客户进程调用WaitNamedPipe 测试指定名单的管道实例是否可用。

命名管道支持字节模式和消息模式,服务器进程在创建命名管道时指定它的默认模式。

服务器和客户进程都可以调用SetnamedPipeHandleState 设置命名管道实例的读操作模式和等待模式。若服务器指定了管道为字节模式,则客户端不能设置消息模式;若服务器指定了消息模式,则客户端允许将它这一端设置为字节模式。

TransactnamedPipe 只能用于消息模式的命名管道,它将一个写和读消息操作合并为一个网络操作。客户和服务器进程都可以使用它。

CallnamedPipe 等价于先调用CreateFile 建立命名管道实例连接,然后调用TransactNamedPipe 发送和接收消息,最后调用CloseHandle 关闭命名管道实例。仅用于客户进程。

管道字节模式的时候是以字节流接收与发送的。每次可以发送不同的字节数,在没有把发送的数据收走(用ReadFile)前也可以再次发送,只要没有超过管道的默认的缓冲区大小 。其实也可以说是我们用的是PIPE_WAIT,所以会是在阻塞模式,也就是说会让数据直接发送到了服务器端的缓冲区中,虽然sever端没有调用ReadFile来读取数据,其实已经发到那一边去了,它不读出来没有关系,我们客户端还是可以继续发送数据的。而且对每次发送的数据大小没有限制,不会说每次都得发送固定大小的数据 。读的那一端也会把接收到的数据作为一个无机的整体,也就是说是没有结构的二进制流。读的时候可以想读出任意的字节数都可以的。如一次发送了5个字节,然后再发送了40个字节 ,服务器端可以一次性全部读出45个字节 也可以每次读出一个字节 。以及小于45的任意字节。

 

3  命名管道的实现

服务器创建命名管道过程:

  1. CreateNamedPipe 创建命名管道的请求交给NtCreateNamedPipeFile。
  2. NtCreateNamedPipeFile 接收到的命名管道的名称未”\??\PIPE\<PipeName>”,该函数把参数组织到一个NAMED_PIPE_CREATE_PARAMETERS结构中,然后调用IoCreateFile 创建任务。
  3. IoCreateFile 中指定CREATE_FILE_TYPE参数,表明是要创建的文件类型:普通的文件、命名管道或者邮件槽。然后,IoCreateFile调用IopCreateFile 。
  4. IopCreateFile 调用ObOpenObjectByName 完成创建工作。
  5. ObOpenObjectByName继续调用ObpLookupObjectName 创建目标对象。
  6. ObpLookupObjectName 判断命名管道的名称名称以“\??\”为前缀,于是从进程对象的DeviceMap 的DosDeviceDirectory 开始解析余下的名称。
  7. 经过”\??\”解析后,接着从“\Global??”目录中解析”PIPE”,这是一个指向设备对象”\Device\NamedPipe”的符号链接对象。符号链接对象的数据类型为OBJECT_SYMBOLIC_LINK,其Parse 方法为ObpParseSymbolicLink。
  8. ObpLookupObjectName 调用ObpParseSymbolicLink 解析余下的名称”<PipeName>”。 ObpParseSymbolicLink 返回STATUS_REPARSE,ObpLookupObjectName重新解析“\Devuce\NamedPipe\<PipeName>”,故重新从根目录开始解析,,最后找到设备对象”\Device\NamedPipe”。接着调用IopParseDevice。
  9. IopParseDevice 调用ObCreateObject 创建一个文件对象(FILE_OBJECT),然后通过IoCallDriver,向设备对象的驱动程序npfs.sys 发送一个IRP_MJ_CREATE_NAMED_PIPE请求,来创建命名管道。
  10. 命名管道驱动程序初始化设备对象“\Device\NamedPipe”,并设置驱动程序对象的I/O分发例程。

Npfs.sys 的内部实现有一个全局的VCB和根目录的DCB,每个管道对象有一个FCB,命名管道的每个实例有一个CCB,每个CCB有两个文件对象指针,分别指向该实例的服务端和客户端文件对象。因为每个命名管道对象可以有多个实例,所以FCB有一个链表成员,将它的所有实例的CCB链接起来。为了提供双向数据传输能力,每个CCB,即命名管道实例,包含两个队列结构,用做数据传输的缓冲区。

命名管道的实现示意图:

服务端通过NtCreateNamedPipe 来创建命名管道,通过对象管理器发送IRP_MJ_CREATE_NAMED_PIPE请求。Npfs.sys 接收到该请求时,若是一个新的命名管道,则创建一个FCB和一个CCB,并初始化FCB,以及CCB中有关服务端的状态;若是已有的命名管道,则npfs 创建一个CCB,将其加入到FCB的CCB链表中,并初始化CCB的服务端状态。

 

客户端连接服务端:

  1. 客户进程通过NtCreateFile 连接命名管道时,它通过对象管理器,向命名管道驱动发送IRP_MJ_CREATE请求。
  2. Npfs.sys 接收到此请求时,通过解析指定的名称,找到FCB,然后找到一个处于监听状态的CCB,并初始化它的客户端状态信息,最后将它置为”已建立连接”的状态。

 

双方收发数据:

  1. 服务器和客户端通过NtReadFile 和NtWriteFile ,根据文件对象的指示,向驱动程序发送IRP_MJ_READ 或IRP_MJ_WRITE请求。
  2. Nptfs 驱动程序利用CCB中的两个数据队列来实现基于管道实例的读写操作,并且支持字节模式和消息模式。

 

命名管道实际上是一个内存中的文件对象,供不同程序之间传递数据或消息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值